Connecteur HDFS pour le stockage d'objets
Le connecteur HDFS (Hadoop Distributed File System) permet à votre application Apache Hadoop de lire et d'écrire des données vers et depuis le service Oracle Cloud Infrastructure Object Storage.
Cette trousse SDK et cet exemple sont des licences doubles fournies dans le cadre des licences Universal Permissive License 1.0 et Apache License 2.0. Le contenu de tierce partie est fourni sous une licence distincte, comme décrit dans le code.
- Services pris en charge :Service de stockage d'objets
- Téléchargement : GitHub ou Maven
- Documentation sur l'API : Informations de référence sur l'API du connecteur HDFS
Conditions requises
Pour utiliser le connecteur HDFS, vous devez avoir :
- Un compte Oracle Cloud Infrastructure.
- Un utilisateur créé dans ce compte, dans un groupe, avec une politique qui accorde les autorisations souhaitées pour tout seau à utiliser. Il peut s'agir d'un utilisateur pour vous-même, une autre personne ou un autre système qui doit appeler l'API. Pour des exemples sur la configuration d'un nouvel utilisateur, d'un groupe, d'un compartiment et d'une politique, voir Ajout d'utilisateurs. Pour une politique de stockage d'objets de base, voir Permettre aux administrateurs du stockage d'objets de gérer des seaux et des objets.
- Java 8
- Une valeur de durée de vie de 60. Pour plus d'informations, voir Configuration de la durée de vie de machine virtuelle Java pour les consultations de nom DNS.
Données d'identification et mots de passe
Si vous utilisez un fichier PEM chiffré pour les données d'identification, la phrase secrète est lue à partir de la configuration à l'aide de la méthode de configuration Hadoop getPassword
. L'option getPassword
vérifie la présence d'un mot de passe dans un fournisseur de sécurité inscrit. Si le fournisseur de sécurité ne contient pas la clé demandée, la phrase secrète en texte brut est lue directement à partir du fichier de configuration.
Configuration de la durée de vie de la JVM pour les consultations de nom DNS
La machine virtuelle Java (JVM) met en mémoire cache les réponses DNS à partir des consultations pendant un certain temps, appelé Durée de vie. Cela garantit un temps de réponse plus rapide pour le code qui nécessite une résolution fréquente des noms.
La JVM utilise la propriété networkaddress.cache.ttl pour spécifier la politique de mise en mémoire cache des consultations de nom DNS. La valeur est un nombre entier qui représente le nombre de secondes pour mettre en mémoire cache la consultation réussie. La valeur par défaut pour de nombreuses machines virtuelles Java, -1
, indique que la consultation doit toujours être mise en mémoire cache.
Comme les ressources dans Oracle Cloud Infrastructure utilisent des noms DNS pouvant être modifiés, nous vous recommandons de remplacer la valeur de durée de vie par 60 secondes. Cela garantit que la nouvelle adresse IP de la ressource est retournée lors de la prochaine interrogation de DNS. Vous pouvez modifier cette valeur de façon globale ou précise pour votre application :
-
Pour définir la durée de vie globalement pour toutes les applications utilisant la JVM, ajoutez la valeur suivante dans le fichier
$JAVA_HOME/jre/lib/security/java.security
:networkaddress.cache.ttl=60
-
Pour définir la durée de vie uniquement pour votre application, définissez les éléments suivants dans le code d'initialisation de votre application :
java.security.Security.setProperty("networkaddress.cache.ttl" , "60");
Installation
Copiez les fichiers JAR regroupés de la bibliothèque et de la bibliothèque de tierce partie dans chaque noeud de la grappe Hadoop afin qu'ils soient inclus dans la variable CLASSPATH de Hadoop.
Trousse SDK pour les artefacts Java et Maven
La création du connecteur HDFS s'appuie sur les artefacts Maven fournis par la trousse SDK Oracle Cloud Infrastructure pour Java. Pour obtenir les artefacts, vous devez télécharger la trousse SDK pour Java et la créer localement. Vous pouvez ensuite créer le connecteur HDFS.
La trousse SDK pour la version du fichier Java que vous téléchargez à partir de la page des versions Oracle doit correspondre à la version du connecteur HDFS figurant dans le fichier
hdfs-connector/pom.xml
du bloc de balise de dépendance qui contient l'attribut groupId
.Connecteur HDFS et artefacts Maven
Le connecteur HDFS est disponible sur Maven Central et JCenter.
Pour utiliser le connecteur HDFS dans votre projet, importez la dépendance de projet suivante. Par exemple :
<dependency>
<groupId>com.oracle.oci.sdk</groupId>
<artifactId>oci-hdfs-connector</artifactId>
<!-- Replace the version below with your required version -->
<version>2.9.2.0</version>
</dependency>
Propriétés
Vous pouvez définir les propriétés de connecteur HDFS suivantes dans le fichier core-site.xml
. La page BmcProperties liste les propriétés supplémentaires que vous pouvez configurer pour une connexion au service de stockage d'objets.
Propriété | Description | Type | Obligatoire |
---|---|---|---|
fs.oci.client.hostname
|
URL du point d'extrémité de l'hôte. Par exemple, |
Chaîne | Oui |
fs.oci.client.auth.tenantId
|
OCID de votre location. Pour obtenir la valeur, voir Clés et OCID requis. |
Chaîne | Oui |
fs.oci.client.auth.userId
|
OCID de l'utilisateur appelant l'API. Pour obtenir la valeur, voir Clés et OCID requis. |
Chaîne | Oui |
fs.oci.client.auth.fingerprint
|
Empreinte pour la paire de clés utilisée. Pour obtenir la valeur, voir Clés et OCID requis. |
Chaîne |
Oui, sauf si vous fournissez un authentificateur personnalisé. |
fs.oci.client.auth.pemfilepath
|
Chemin complet et nom de fichier de la clé privée servant à l'authentification. Le fichier doit se trouver dans le système de fichiers local. | Chaîne | Oui, sauf si vous fournissez un authentificateur personnalisé. |
fs.oci.client.auth.passphrase
|
Phrase secrète utilisée pour la clé si elle est chiffrée. | Chaîne | Uniquement si votre clé est chiffrée. |
fs.oci.client.regionCodeOrId
|
Code ou identificateur de région utilisé pour établir le nom du point d'extrémité du service de stockage d'objets. | Chaîne | Non |
Vous pouvez indiquer qu'une valeur de propriété s'applique à un seau spécifique en ajoutant
.<bucket_name>.<namespace_name>
au nom de la propriété.Définition du point d'extrémité de la région
Vous pouvez utiliser plusieurs méthodes pour définir le point d'extrémité de la région pour le connecteur HDFS :
- Définir la propriété de nom d'hôte dans
core-site.xml
- Définir la propriété de code ou d'identificateur de région dans
core-site.xml
- Autoriser le client ObjectStorage à récupérer le point d'extrémité au moyen du service de métadonnées d'instance
Configuration des propriétés à l'aide de core-site.xml
Cet exemple montre comment les propriétés peuvent être configurées dans un fichier core-site.xml
(les OCID sont abrégés par souci de concision) :
<configuration>
...
<property>
<name>fs.oci.client.hostname</name>
<value>https://objectstorage.us-ashburn-1.oraclecloud.com</value>
</property>
<property>
<name>fs.oci.client.hostname.myBucket.myNamespace</name>
<value>https://objectstorage.us-phoenix-1.oraclecloud.com</value><!-- Use Phoenix for myBucket@myNamespace -->
</property>
<property>
<name>fs.oci.client.auth.tenantId</name>
<value>ocid1.tenancy.oc1..exampleuniqueID</value>
</property>
<property>
<name>fs.oci.client.auth.userId</name>
<value>ocid1.user.oc1..exampleuniqueID</value>
</property>
<property>
<name>fs.oci.client.auth.fingerprint</name>
<value>20:3b:97:13:55:1c:5b:0d:d3:37:d8:50:4e:c5:3a:34</value>
</property>
<property>
<name>fs.oci.client.auth.pemfilepath</name>
<value>~/.oci/oci_api_key.pem</value>
</property>
...
</configuration>
Utilisation des principaux d'instance pour l'authentification
Oracle fournit des principaux d'instance afin que vous n'ayez plus à configurer de données d'identification des utilisateurs ni à fournir des fichiers PEM pour les services en cours d'exécution sur des instances. Chaque instance possède sa propre identité et s'authentifie à l'aide des certificats que les principaux d'instance lui ajoutent.
Pour utiliser l'authentification fondée sur des principaux d'instance avec le connecteur HDFS, il vous suffit de fournir la propriété fs.oci.client.custom.authenticator
et de régler la valeur à com.oracle.bmc.hdfs.auth.InstancePrincipalsCustomAuthenticator
.
Comme les principaux d'instance fournissent au connecteur un authentificateur personnalisé, il n'est plus nécessaire de configurer les propriétés suivantes :
fs.oci.client.auth.tenantId
fs.oci.client.auth.userId
fs.oci.client.auth.fingerprint
fs.oci.client.auth.pemfilepath
fs.oci.client.auth.passphrase
L'exemple de code suivant illustre l'utilisation des principaux d'instance pour l'authentification avec le connecteur HDFS :
<?xml version="1.0"?>
<configuration>
<property>
<name>fs.oci.client.hostname</name>
<value>https://objectstorage.us-phoenix-1.oraclecloud.com</value>
</property>
<property>
<name>fs.oci.client.custom.authenticator</name>
<value>com.oracle.bmc.hdfs.auth.InstancePrincipalsCustomAuthenticator</value>
</property>
</configuration>
Pour plus d'informations sur les principaux d'instance, voir Annonce concernant les principaux d'instance pour la gestion des identités et des accès.
Utilisation des principaux de ressource pour l'authentification
Comme pour les principaux d'instance, Oracle fournit des principaux de ressource pour authentifier les ressources qui ne sont pas des instances (un carnet jupyter, par exemple). Chaque ressource possède sa propre identité et s'authentifie à l'aide des certificats qui y sont ajoutés.
Pour utiliser l'authentification fondée sur des principaux de ressource avec le connecteur HDFS, il vous suffit de fournir la propriété fs.oci.client.custom.authenticator
et de régler la valeur à com.oracle.bmc.hdfs.auth.ResourcePrincipalsCustomAuthenticator
.
Comme l'utilisation des principaux de ressource fournit au connecteur un authentificateur personnalisé, il n'est pas nécessaire de configurer les propriétés suivantes :
fs.oci.client.auth.tenantId
fs.oci.client.auth.userId
fs.oci.client.auth.fingerprint
fs.oci.client.auth.pemfilepath
fs.oci.client.auth.passphrase
L'exemple de code suivant illustre l'utilisation des principaux de ressource pour l'authentification avec le connecteur HDFS :
<?xml version="1.0"?>
<configuration>
<property>
<name>fs.oci.client.hostname</name>
<value>https://objectstorage.us-phoenix-1.oraclecloud.com</value>
</property>
<property>
<name>fs.oci.client.custom.authenticator</name>
<value>com.oracle.bmc.hdfs.auth.ResourcePrincipalsCustomAuthenticator</value>
</property>
</configuration>
Pour plus d'informations sur les principaux de ressource, voir Utilisation des principaux de ressource dans le service de science des données.
Utilisation de l'authentification Kerberos
Oracle prend en charge l'authentification Kerberos pour la connexion au service de stockage d'objets à l'aide du connecteur HDFS.
- Dans
core-site.xml
, réglez la propriétéfs.oci.client.custom.authenticator
àcom.oracle.bmc.hdfs.auth.spnego.UPSTAuthenticationCustomAuthenticator
. - Dans
core-site.xml
, définissez les propriétés suivantes :fs.oci.client.upst.domainUrl
-
fs.oci.client.upst.clientId
-
fs.oci.client.upst.clientSecret
-
fs.oci.client.upst.tokenExchangeServicePrincipal
-
fs.oci.client.upst.userPrincipal
fs.oci.client.upst.issuer
fs.oci.client.keytab.path
fs.oci.client.kinit.internal.mode
L'exemple de fichier core-site.xml
suivant illustre l'utilisation de Kerberos avec l'authentification par jeton SPNEGO avec le connecteur HDFS :
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>fs.oci.client.hostname</name>
<value>https://objectstorage.us-phoenix-1.oraclecloud.com</value>
</property>
<property>
<name>fs.oci.client.auth.tenantId</name>
<value></value>
</property>
<property>
<name>fs.oci.client.auth.userId</name>
<value></value>
</property>
<property>
<name>fs.oci.client.custom.authenticator</name>
<value>com.oracle.bmc.hdfs.auth.spnego.UPSTAuthenticationCustomAuthenticator</value>
</property>
<property>
<name>fs.oci.client.upst.tokenExchangeServicePrincipal</name>
<value><!-- Service Principal for generating SPNEGO token --></value>
</property>
<property>
<name>fs.oci.client.upst.userPrincipal</name>
<value><!-- User Principal for generating SPNEGO token --></value>
</property>
<property>
<name>fs.oci.client.upst.issuer</name>
<value><!-- Issuer for generating SPNEGO token --></value>
</property>
<property>
<name>fs.oci.client.upst.domainUrl</name>
<value><!-- Domain application client ID for IAM token exchange --></value>
</property>
<property>
<name>fs.oci.client.upst.clientId</name>
<value><!-- Domain application client ID for IAM token exchange --></value>
</property>
<property>
<name>fs.oci.client.upst.clientSecret</name>
<value><!-- Domain application client secret for IAM token exchange --></value>
</property>
<property>
<name>fs.oci.client.keytab.path</name>
<value><!-- File path to the keytab used for token exchange --></value>
</property>
</configuration>
Pour plus d'informations sur Kerberos, voir le tutoriel sur le protocole Kerberos.
Pour plus d'informations sur SPNEGO, voir le document RFC 4178.
Utilisation du connecteur Jersey par défaut HttpUrlConnectorProvider
À partir de la version 3.3.0.7.0.0, HDFS prend en charge l'utilisation du client Apache par défaut pour effectuer des appels de service OCI. En effet, le connecteur HDFS utilise la trousse SDK pour Java pour envoyer des demandes au serveur. La trousse SDK pour Java prend en charge l'utilisation du connecteur Jersey par défaut ApacheConnectorProvider
au lieu du connecteur Jersey HttpUrlConnectorProvider
pour permettre au client HTTP Apache d'effectuer des appels de service OCI.
Pour revenir à l'ancien client Jersey par défaut, réglez la propriété fs.oci.client.jersey.default.connector.enabled
dans le fichier core-site.xml
à true
. Par défaut, cette valeur est réglée à false
.
Optimisation de la performance avec le connecteur Apache pour HDFS
Le connecteur Apache prend en charge deux stratégies de fermeture de connexion : ApacheConnectionClosingStrategy.GracefulClosingStrategy
et ApacheConnectionClosingStrategy.ImmediateClosingStrategy
.
Lorsque vous utilisez ApacheConnectionClosingStrategy.GracefulClosingStrategy
, les flux retournés à partir d'une réponse sont lus jusqu'à la fin du flux lors de la fermeture de celui-ci. Cela peut entraîner un délai supplémentaire lors de la fermeture du flux avec une lecture partielle, selon la taille du flux restant. Pour éviter ce délai, envisagez d'utiliser ApacheConnectionClosingStrategy.ImmediateClosingStrategy
pour les fichiers volumineux avec des lectures partielles. Avec ApacheConnectionClosingStrategy.ImmediateClosingStrategy
, les flux ne sont pas lus jusqu'à la fin lors de leur fermeture, ce qui peut améliorer la performance. Notez que ApacheConnectionClosingStrategy.ImmediateClosingStrategy
prend plus de temps lors de l'utilisation de la lecture partielle pour les flux dont la taille est inférieure à 1 Mo.
Définition de la stratégie de fermeture de connexion
Définissez la stratégie de fermeture de connexion en définissant la propriété fs.oci.client.apache.connection.closing.strategy
dans le fichier core-site.xml
:
- Pour utiliser
ApacheConnectionClosingStrategy.GracefulClosingStrategy
, réglezfs.oci.client.apache.connection.closing.strategy
àgraceful
. - Pour utiliser
ApacheConnectionClosingStrategy.ImmediateClosingStrategy
, réglezfs.oci.client.apache.connection.closing.strategy
àimmediate
.
Ces stratégies de fermeture fonctionnent uniquement avec le connecteur Apache pour HDFS et sont ignorées lors de l'utilisation du connecteur Jersey par défaut.
Retour au connecteur Jersey par défaut
Le connecteur Jersey par défaut lit les flux jusqu'à la fin, puis réutilise le flux, ce qui peut améliorer la performance par rapport au connecteur Apache pour HDFS dans certains scénarios. Si ces stratégies de fermeture de connexion Apache ne produisent pas des résultats optimaux pour vos cas d'utilisation, vous pouvez revenir au connecteur Jersey par défaut HttpUrlConnectorProvider. Vous pouvez revenir à l'ancien client Jersey par défaut en réglant la propriété fs.oci.client.jersey.default.connector.enabled
dans le fichier core-site.xml
à true
. Par défaut, cette valeur est réglée à false
.
Pour plus d'informations, voir : https://github.com/oracle/oci-java-sdk/blob/master/ApacheConnector-README.md.
Réserve de connexions dans HDFS
Vous pouvez définir le nombre maximal de connexions dans la réserve de connexions HDFS.
Pour ce faire, remplacez la propriété fs.oci.client.apache.max.connection.pool.size
dans le fichier core-site.xml
par un entier positif qui spécifie le nombre de connexions dans la réserve.
Cette propriété n'est prise en charge que si vous utilisez
ApacheConnector
pour HDFS; sinon, elle est ignorée.Points d'extrémité dédiés
fs.oci.client.hostname
ou la propriété fs.oci.realmspecific.endpoint.template.enabled
de l'indicateur de modèle de point d'extrémité dans core-site.xml
. Si vous définissez la propriété du modèle de point d'extrémité, vous devez également définir
fs.oci.client.regionCodeOrId
dans core-site.xml
.La valeur définie au moyen du nom d'hôte dans
core-site.xml
a préséance sur la valeur définie au moyen de la propriété de modèle de point d'extrémité dans core-site.xml
.fs.oci.client.hostname
:<property>
<name>fs.oci.client.hostname</name>
<value>https://my-namespace.objectstorage.me-dubai-1.oci.customer-oci.com</value>
</property>
fs.oci.realmspecific.endpoint.template.enabled
:<property>
<name>fs.oci.client.regionCodeOrId</name>
<value>me-dubai-1</value>
</property>
<property>
<name>fs.oci.realmspecific.endpoint.template.enabled</name>
<value>true</value>
</property>
Configuration d'un mandataire HTTP
Vous pouvez définir les propriétés facultatives suivantes dans le fichier core-site.xml
pour configurer un mandataire HTTP :
Propriété | Description | Type | Obligatoire |
---|---|---|---|
fs.oci.client.proxy.uri
|
URI du point d'extrémité du mandataire. Par exemple, |
Chaîne | Non |
fs.oci.client.proxy.username
|
Nom d'utilisateur pour l'authentification auprès du mandataire. | Chaîne | Non |
fs.oci.client.proxy.password
|
Mot de passe pour l'authentification auprès du mandataire. | Chaîne | Non |
fs.oci.client.multipart.allowed
|
Active le gestionnaire de chargement pour la prise en charge des chargements en plusieurs parties. | Booléen | Non |
fs.oci.client.multipart.minobjectsize.mb
|
Spécifie la taille minimale de l'objet en mébioctets pour le gestionnaire de chargement. |
Entier | Non |
fs.oci.client.multipart.partsize.mb
|
Spécifie la taille de la partie en mébioctets pour le gestionnaire du chargement. | Entier | Non |
La configuration d'un mandataire permet l'utilisation de
ApacheConnectorProvider
lors des connexions au Stockage d'objets. Les demandes sont mises en mémoire tampon, ce qui peut avoir une incidence sur l'utilisation de la mémoire lors du chargement d'objets volumineux. Il est recommandé d'activer les chargements en plusieurs parties et d'ajuster les propriétés des parties pour gérer la consommation de la mémoire.Chargements d'objets volumineux
Les objets volumineux sont chargés dans le stockage d'objets à l'aide de chargements en plusieurs parties. Le fichier est fractionné en parties plus petites qui sont chargées en parallèle, ce qui réduit le temps de chargement. Cela permet également au connecteur HDFS de charger à nouveau uniquement les parties en échec et d'éviter ainsi l'échec de l'ensemble du chargement. Toutefois, il arrive que les chargements échouent de façon temporaire. Dans ces cas, le connecteur tentera d'abandonner les fichiers partiellement chargés. Comme ces fichiers se cumulent (et que vous serez facturé pour le stockage), listez les chargements périodiquement, puis après un certain nombre de jours, abandonnez-les manuellement à l'aide de la trousse SDK pour Java.
Vous pouvez trouver des informations sur l'utilisation de l'API Stockage d'objets pour gérer les chargements en plusieurs parties sous Utilisation des chargements en plusieurs parties.
Si vous préférez ne pas utiliser les chargements en plusieurs parties, vous pouvez les désactiver en réglant la propriété
fs.oci.client.multipart.allowed
à false
.Meilleures pratiques
Les sections qui suivent contiennent les meilleures pratiques pour optimiser l'utilisation et la performance.
Nom de répertoire
Il n'existe aucun répertoire réel dans le stockage d'objets. Le regroupement de répertoires est une fonction d'une convention d'attribution de nom, où les objets utilisent les délimiteurs /
dans leur nom. Par exemple, un objet nommé a/example.json
implique qu'il existe un répertoire nommé a
. Toutefois, si cet objet est supprimé, le répertoire a
est également supprimé implicitement. Pour préserver la sémantique du système de fichiers où le répertoire peut exister sans présence de fichiers, le connecteur HDFS crée un objet réel dont le nom se termine par /
avec un chemin qui représente le répertoire (par exemple, il crée un objet nommé a/
). Désormais, la suppression de a/example.json
n'affecte pas l'existence du répertoire a
, car l'objet a/
garantit sa présence. En revanche, il est tout à fait possible qu'un utilisateur puisse supprimer cet objet a/
sans supprimer les fichiers et les répertoires connexes. Le connecteur HDFS supprimera uniquement l'objet de dossier s'il n'existe aucun objet sous ce chemin. L'objet de dossier lui-même est de zéro octet.
Système de fichiers incohérent
La suppression d'un répertoire entraîne la suppression de tous les objets qui commencent par le préfixe représentant ce répertoire. HDFS vous permet d'interroger le statut d'un fichier ou d'un répertoire. Le statut de fichier d'un répertoire est mis en oeuvre en vérifiant que l'objet de dossier pour ce répertoire existe. Il est toutefois possible que l'objet de dossier ait été supprimé, mais que des objets ayant ce préfixe existent encore. Prenons, par exemple, les objets suivants :
a/b/example.json
a/b/file.json
a/b/
HDFS peut vérifier que le répertoire /a/b/
existe et est un répertoire, et le balayage aurait pour résultat example.json
et file.json
. Toutefois, si l'objet a/b/
a été supprimé, le système de fichiers pourrait avoir un état incohérent. Vous pouvez interroger le système pour tous les fichiers du répertoire /a/b/
et rechercher les deux entrées, mais l'interrogation du statut du répertoire /a/b/
réel générerait une exception, car le répertoire n'existe pas. Le connecteur HDFS ne tente pas de réparer l'état du système de fichiers.
Création de fichier
Le service de stockage d'objets prend en charge des objets d'une taille de plusieurs gigaoctets. La création de fichiers se fera normalement en écrivant dans un fichier temporaire, puis en chargeant le contenu du fichier lorsque le flux est fermé. L'espace temporaire doit être suffisant pour traiter des chargements multiples. Le répertoire temporaire utilisé est contrôlé par la propriété de configuration hadoop.tmp.dir
.
Prise en charge de la lecture/recherche
Lorsque des tampons en mémoire sont activés (fs.oci.io.read.inmemory
), la recherche est totalement prise en charge, car l'intégralité du fichier est mis en mémoire tampon dans un tableau d'octets. Si le tampon en mémoire n'est pas activé (probablement parce que les tailles d'objet sont volumineuses), la recherche est mise en oeuvre en fermant le flux et en effectuant une nouvelle demande d'intervalle commençant au décalage spécifié.
Liste de répertoires
La fonction permettant de lister un répertoire est, par essence, une opération qui liste les seaux avec un préfixe et un délimiteur spécifiés. Pour créer une instance de statut de fichier (FileStatus) HDFS pour chaque clé, le connecteur effectue une demande HEAD supplémentaire afin d'obtenir les métadonnées d'objet pour chaque clé. Cette opération sera requise tant que le stockage d'objets ne prendra pas en charge les données d'opération de liste enrichie.
Format d'URI pour les systèmes de fichiers et les fichiers
Les systèmes de fichiers et les fichiers HDFS sont référencés par des URI. Le schéma de l'URI spécifie le type de système de fichiers. La partie restante de l'URI peut être interprétée librement par la mise en oeuvre du système de fichiers.
Comme le stockage d'objets est un magasin d'objets, sa capacité à nommer les objets comme s'ils étaient des fichiers d'un système de données est utilisée pour reproduire un système de données réel.
Racine
La racine du système de fichiers du stockage d'objets est indiquée par un chemin où le composant d'autorité comprend le nom du seau et le nom de l'espace de noms, comme illustré ci-après :
Dans les exemples, "
MyBucket
" et "MyNamespace
" sont des paramètres fictifs et doivent être remplacés par des valeurs appropriées.
oci://MyBucket@MyNamespace/
Il s'agit toujours de la racine du système de fichiers. La raison qui sous-tend l'utilisation d'une autorité à la fois pour le seau et l'espace de noms réside dans le fait que HDFS n'autorise que la partie autorité pour déterminer où le système de fichiers est; la partie du chemin indique seulement le chemin d'accès à la ressource (par conséquent, "oci/MyNamespace/MyBucket" ne fonctionnera pas, par exemple). Notez que le caractère @
n'est pas valide pour les seaux ou les espaces de noms et qu'il doit pouvoir être analysé correctement par l'autorité.
Sous-répertoires
Les sous-répertoires n'existent pas réellement, mais peuvent être reproduits en créant des objets avec des caractères /
. Par exemple, deux fichiers nommés a/b/c/example.json
et a/b/d/path.json
s'afficheraient comme s'ils se trouvaient dans un répertoire a/b
commun. Pour ce faire, utilisez l'interrogation basée sur les préfixes et délimiteurs du stockage d'objets. Dans l'exemple indiqué, le référencement d'un sous-répertoire en tant qu'URI se présenterait comme suit :
oci://MyBucket@MyNamespace/a/b/
Objets/Fichiers
Un objet nommé a/b/c/example.json
est référencé en tant que :
oci://MyBucket@MyNamespace/a/b/c/example.json
Journalisation
La journalisation dans le connecteur s'effectue au moyen de SLF4J. SLF4J est une abstraction de journalisation qui permet l'utilisation d'une bibliothèque de journalisation fournie par l'utilisateur (par exemple, log4j). Pour plus d'informations, consultez le manuel SLF4J.
L'exemple suivant montre comment activer la journalisation de base pour une sortie standard.
- Téléchargez le fichier JAR de liaison simple SLF4J : SLF4J Simple Binding
- Ajoutez le fichier JAR à la variable classpath
- Ajoutez l'argument de machine virtuelle suivant pour permettre la journalisation du niveau de débogage (par défaut, le niveau d'information est utilisé) :
-Dorg.slf4j.simpleLogger.defaultLogLevel=debug
Vous pouvez configurer des options de journalisation plus avancées en utilisant la liaison log4j.
Utilisation de la structure de surveillance
Le connecteur HDFS pour le stockage d'objets comprend un cadre de surveillance qui fournit des mesures sur les opérations effectuées à l'aide du connecteur. La structure de surveillance fournit une interface qui peut être mise en oeuvre pour consommer/écouter les mesures générées par le connecteur. Vous pouvez fournir une mise en oeuvre personnalisée de cette interface ou utiliser la mise en oeuvre de télémétrie publique OCI incluse dans ce cadre.
Introduction
Pour commencer à utiliser le cadre de surveillance du connecteur HDFS, vous devez définir les propriétés suivantes. Une fois ces propriétés définies pour OCIMonitoring
, vous pouvez utiliser la vue Explorateur de mesures dans la console OCI pour observer les mesures émises à partir du connecteur HDFS.
fs.oci.mon.consumer.plugins
fs.oci.mon.consumer.plugins
prend une liste séparée par des virgules de noms de classe complets pour les mises en oeuvre de l'interface de surveillance. com.oracle.bmc.hdfs.monitoring.OCIMonitorPlugin
doit être utilisé dans la liste si vous voulez que les mesures soient émises pour la télémétrie publique OCI.<property>
<name>fs.oci.mon.consumer.plugins</name>
<value>com.oracle.bmc.hdfs.monitoring.OCIMonitorPlugin,com.your.new.plugin.PluginImpl1</value>
</property>
fs.oci.mon.grouping.cluster.id
fs.oci.mon.grouping.cluster.id
spécifie l'identificateur de la grappe HDFS ou de tout autre ID dans lequel vous voulez regrouper les mesures. Il s'agit d'une propriété obligatoire, qui est également utilisée par OCIMonitorPlugin
pour marquer des mesures. Cette propriété est visible en tant que dimension dans l'interface utilisateur et l'API de télémétrie publique OCI.<property>
<name>fs.oci.mon.grouping.cluster.id</name>
<value>hdfs-sample-cluster-id</value>
</property>
Propriétés com.oracle.bmc.hdfs.monitoring.OCIMonitorPlugin
Si la propriété com.oracle.bmc.hdfs.monitoring.OCIMonitorPlugin
est activée, les propriétés suivantes sont applicables :
fs.oci.mon.telemetry.ingestion.endpoint
fs.oci.mon.telemetry.ingestion.endpoint
permet de configurer le point d'extrémité d'ingestion de télémétrie de la surveillance OCI. Pour plus d'informations, consultez la liste des points disponibles.
<property>
<name>fs.oci.mon.telemetry.ingestion.endpoint</name>
<value>https://telemetry-ingestion.us-ashburn-1.oraclecloud.com</value>
</property>
fs.oci.mon.compartment.ocid
fs.oci.mon.compartment.ocid
est utilisée pour configurer le compartiment OCI auquel les mesures seront attachées. Il s'agit généralement du compartiment auquel les seaux appartiennent.<property>
<name>fs.oci.mon.compartment.ocid</name>
<value>ocid1.compartment.oc1..sample.compartment.id</value>
</property>
fs.oci.mon.bucket.level.enabled
fs.oci.mon.bucket.level.enabled
détermine si le nom du seau doit être attaché en tant que dimension aux mesures émises.<property>
<name>fs.oci.mon.bucket.level.enabled</name>
<value>true</value>
</property>
fs.oci.mon.ns.name
fs.oci.mon.ns.name
contrôle l'espace de noms utilisé pour les mesures émises par le connecteur HDFS. Un exemple d'espace de noms pourrait être "hdfsconnector". Cela résidera le long d'autres espaces de noms prédéfinis tels que oci_objectstorage
dans la télémétrie publique.<property>
<name>fs.oci.mon.ns.name</name>
<value>name.of.namespace.on.oci.telemetry</value>
</property>
fs.oci.mon.rg.name
fs.oci.mon.rg.name
définit le nom du groupe de ressources utilisé pour contenir les mesures. Il peut s'agir de n'importe quel nom logique pour regrouper des ressources qui seront surveillées ensemble. Ce nom de groupe de ressources apparaîtra sous l'espace de noms qui a été sélectionné précédemment dans la télémétrie publique OCI.<property>
<name>fs.oci.mon.rg.name</name>
<value>name.of.resource.group.on.oci.telemetry</value>
</property>
Créer votre propre consommateur pour les mesures
com.oracle.bmc.hdfs.monitoring.OCIMonitorConsumerPlugin
, vous devez définir deux méthodes :accept
shutdown
Les classes d'extension doivent avoir un constructeur avec la même signature que celle de la classe OCIMonitorConsumerPlugin
.
public OCIMonitorConsumerPlugin(BmcPropertyAccessor propertyAccessor, String bucketName, String monitoringGroupingID, String namespaceName);
/**
* This class that has to be extended by any plugin, that wants to consume the metrics emitted by OCI HDFS connector.
*/
public abstract class OCIMonitorConsumerPlugin {
/**
* This method will be called on each plugin, by the OCI monitoring framework, whenever it wants to emit out a metric.
* This method should finish as quickly as possible, so the consumer of this should ideally handover the
* ocimetric and stage it elsewhere for processing, instead of trying to deal with it in the accept call itself.
* @param ociMetric The metric that is being emitted by the OCI HDFS connector
*/
public void accept(OCIMetric ociMetric);
/**
* This shutdown method will be called on the implementing plugins, whenever the JVM is shutting down.
* It could be used to cleanup, finish pending tasks before exit.
*/
public void shutdown();
}
La classe OCIMetric
peut être mise en oeuvre de trois façons :
OCIMetric
simple avec les champs suivants :public class OCIMetric {
/**
* The time in milliseconds (epoch) when the metric was recorded.
*/
private final long recordedTime;
/**
* The overall time taken by the operation to complete/error-out in milliseconds.
*/
private final double overallTime;
/**
* The operation key. This will be one of {"LIST", "HEAD", "WRITE", "READ", "DELETE", "RENAME"}
*/
private final String key;
/**
* The boolean error indicates whether the operation errored out.
*/
private final boolean error;
/**
* The target OCI bucket where the operation was attempted to.
*/
private final String bucketName;
}
OCIMetricWithThroughput
qui étend OCIMetric
et comporte des champs supplémentaires pour le débit et les octets transférés. Ceci s'applique aux opérations READ et WRITE :public class OCIMetricWithThroughput extends OCIMetric {
/**
* The throughput that was recorded for the operation in bytes/second
*/
private final double throughput;
/**
* The total count of bytes that were transferred in or out.
*/
private final double bytesTransferred;
}
OCIMetricWithFBLatency
qui étend OCIMetricWithThroughput
, avec un délai supplémentaire jusqu'au champ de latence du premier octet. Cela ne s'applique qu'aux opérations READ :public class OCIMetricWithFBLatency extends OCIMetricWithThroughput {
/**
* The time to first byte when a read operation was performed in milliseconds.
*/
private final double ttfb;
}
Exemple de tâche Hadoop
package com.oracle.oci.hadoop.example;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import org.apache.commons.io.IOUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FSDataOutputStream;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.oracle.oci.hdfs.BmcFilesystem;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
public class SampleOracleBmcHadoopJob
{
private static final String SAMPLE_JOB_PATH = "/samplehadoopjob";
private static final String INPUT_FILE = SAMPLE_JOB_PATH + "/input.dat";
private static final String OUTPUT_DIR = SAMPLE_JOB_PATH + "/output";
// non-static since this is the runner class it needs to initialize after we set the properties
private final Logger log = LoggerFactory.getLogger(SampleOracleBmcHadoopJob.class);
/**
* Runner for sample hadoop job. This expects 3 args: path to configuration file, Object Store namespace, Object
* Store bucket. To run this, you must:
*{@code
*
Create a standard hadoop configuration file
*
Create the bucket ahead of time.
*}
* This runner will create a test input file in a file '/samplehadoopjob/input.dat', and job results will be written
* to '/samplehadoopjob/output'.
*
* @param args
* 1) path to configuration file, 2) namespace, 3) bucket
* @throws Exception
*/
public static void main(final String[] args) throws Exception
{
if (args.length != 3)
{
throw new IllegalArgumentException(
"Must have 3 args: 1) path to config file, 2) object storage namespace, 3) object storage bucket");
}
// redirect all logs to sysout
System.setProperty("org.slf4j.simpleLogger.logFile", "System.out");
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "debug");
final SampleOracleBmcHadoopJob job = new SampleOracleBmcHadoopJob(args[0], args[1], args[2]);
System.exit(job.execute());
}
private final String configurationFilePath;
private final String namespace;
private final String bucket;
public int execute() throws IOException, ClassNotFoundException, InterruptedException, URISyntaxException
{
log.info("Creating hadoop configuration");
final Configuration configuration = this.createConfiguration(this.configurationFilePath);
final String authority = this.bucket + "@" + this.namespace;
final String uri = "oci://" + authority;
log.info("Using uri: {}", uri);
log.info("Creating job inputs");
this.setup(uri, configuration);
log.info("Creating job");
final Job job = this.createJob(configuration);
final String in = uri + INPUT_FILE;
final String out = uri + OUTPUT_DIR;
log.info("Using input: {}", in);
log.info("Using output: {}", out);
FileInputFormat.addInputPath(job, new Path(in));
FileOutputFormat.setOutputPath(job, new Path(out));
log.info("Executing job...");
final int response = job.waitForCompletion(true) ? 0 : 1;
log.info("Attempting to read job results");
this.tryReadResult(uri, configuration);
return response;
}
private Configuration createConfiguration(final String configFilePath)
{
final Configuration configuration = new Configuration();
configuration.addResource(new Path(configFilePath));
return configuration;
}
private void setup(final String uri, final Configuration configuration) throws IOException, URISyntaxException
{
try (final BmcFilesystem fs = new BmcFilesystem())
{
fs.initialize(new URI(uri), configuration);
fs.delete(new Path(SAMPLE_JOB_PATH), true);
final FSDataOutputStream output = fs.create(new Path(INPUT_FILE));
output.writeChars("example\npath\ngak\ntest\nexample\ngak\n\ngak");
output.close();
}
}
private Job createJob(final Configuration configuration) throws IOException
{
final Job job = Job.getInstance(configuration, "word count");
job.setJarByClass(SampleOracleBmcHadoopJob.class);
job.setMapperClass(SimpleMapper.class);
job.setCombinerClass(SimpleReducer.class);
job.setReducerClass(SimpleReducer.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
return job;
}
private void tryReadResult(final String uri, final Configuration configuration)
throws IOException, URISyntaxException
{
try (final BmcFilesystem fs = new BmcFilesystem())
{
fs.initialize(new URI(uri), configuration);
// this should be the output file name, but that could change
final FSDataInputStream input = fs.open(new Path(OUTPUT_DIR + "/part-r-00000"));
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
IOUtils.copy(input, baos);
log.info("\n=====\n" + baos.toString() + "=====");
input.close();
}
}
}
package com.oracle.oci.hadoop.example;
import java.io.IOException;
import java.util.StringTokenizer;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class SimpleMapper extends Mapper
{
private final static IntWritable one = new IntWritable(1);
private final Text word = new Text();
@Override
public void map(final Object key, final Text value, final Context context) throws IOException, InterruptedException
{
final StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens())
{
this.word.set(itr.nextToken());
context.write(this.word, one);
}
}
}
package com.oracle.oci.hadoop.example;
import java.io.IOException;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;
public class SimpleReducer extends Reducer
{
private final IntWritable result = new IntWritable();
@Override
public void reduce(final Text key, final Iterable values, final Context context)
throws IOException, InterruptedException
{
int sum = 0;
for (final IntWritable val : values)
{
sum += val.get();
}
this.result.set(sum);
context.write(key, this.result);
}
}
Dépannage
Cette section contient des informations de dépannage pour le connecteur HDFS.
Dépannage des erreurs de service
Toute opération résultant d'une erreur de service provoquera la génération d'une exception de type com.oracle.bmc.model.BmcException par le connecteur HDFS. Pour plus d'informations sur les erreurs de service communes retournées par OCI, voir Erreurs d'API.
Erreurs de taille de clé de chiffrement Java
Le connecteur HDFS peut uniquement traiter les clés de 128 bits ou de longueur inférieure. Les utilisateurs reçoivent une exception de clé non valide et des erreurs de taille de clé non autorisée lorsqu'ils utilisent des clés plus longues, telles qu'AES256. Utilisez l'une des solutions de contournement suivantes pour résoudre ce problème :
- Utilisez une clé de 128 bits, par exemple AES128.
-
Installez Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction à partir de l'emplacement suivant : http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
Contributions
Vous avez une solution pour un bogue ou une nouvelle fonctionnalité que vous aimeriez partager? La trousse SDK est une solution à code source libre qui accepte les demandes d'extraction sur GitHub.
Avis
Si vous souhaitez recevoir un avis lorsqu'une nouvelle version du connecteur HDFS est publiée, abonnez-vous au flux Atom.
Questions ou rétroaction
Pour rester en contact :
- Problèmes GitHub : Pour signaler des bogues et soumettre des demandes de fonction
- Stack Overflow : Utilisez les balises oracle-cloud-infrastructure et oci-hdfs-connector dans votre publication.
- Section Outils pour développeurs dans les forums Oracle Cloud
- My Oracle Support