MaxCompute ne fournit pas de plug-in de développement dédié pour Graph. Utilisez Eclipse pour développer et déboguer des programmes MaxCompute Graph.
Le flux de travail de développement est le suivant :
Écrivez votre code Graph et déboguez-le localement pour les tests de base.
Déboguez sur cluster pour valider les résultats.
Exemple de développement
L'exemple suivant utilise l'algorithme SSSP pour développer et déboguer un programme Graph dans Eclipse.
Procédure :
Créez un projet Java nommé graph_examples.
Ajoutez les packages JAR du répertoire lib du client MaxCompute au Java Build Path de votre projet Eclipse. Dans l'onglet Libraries de la page Java Build Path, sélectionnez mapreduce-api.jar, développez-le, puis double-cliquez sur Javadoc location. Sélectionnez Javadoc URL et saisissez
http://odps.alibaba-inc.com/doc/prdoc/odps_graph/api/.-
Développez le programme MaxCompute Graph.
Une pratique courante consiste à copier et modifier un exemple existant, tel que l'algorithme Single Source Shortest Path. Dans cet exemple, seul le chemin du package est modifié en package com.aliyun.odps.graph.example.
-
Compilez et empaquetez le programme.
Dans Eclipse, cliquez avec le bouton droit sur le répertoire source (le répertoire src dans la figure) et choisissez pour générer un package JAR. Choisissez un chemin de destination pour le package JAR, par exemple D:\\odps\\clt\\odps-graph-example-sssp.jar.
Utilisez le client MaxCompute pour exécuter la tâche SSSP. Pour plus d'informations, consultez la rubrique Exécution d'une tâche Graph.
Débogage local
MaxCompute Graph prend en charge un mode de débogage local qui permet le débogage avec points d'arrêt dans Eclipse.
Procédure :
Téléchargez le package Maven odps-graph-local.
Dans votre projet Eclipse, cliquez avec le bouton droit sur le fichier de programme principal de la tâche Graph (le fichier contenant la fonction
main) et sélectionnez .Dans l'onglet Arguments, définissez Program arguments sur 1 sssp_in sssp_out.
-
Dans l'onglet Arguments, définissez les VM arguments comme suit.
-Dodps.runner.mode=local -Dodps.project.name=<project.name> -Dodps.end.point=<end.point> -Dodps.access.id=<access.id> -Dodps.access.key=<access.key>Définissez également les paramètres du programme dans Program arguments. Par exemple, utilisez
1 sssp_in sssp_out, qui représentent respectivement le nœud de départ, le nom de la table d'entrée et le nom de la table de sortie. -
Pour le mode local, lorsque le paramètre odps.end.point n'est pas spécifié, vous devez créer les tables sssp_in et sssp_out dans le répertoire warehouse et ajouter des données à la table d'entrée sssp_in. Le code suivant montre des exemples de données d'entrée.
1,"2:2,3:1,4:4" 2,"1:2,3:2,4:1" 3,"1:1,2:2,5:1" 4,"1:4,2:1,5:1" 5,"3:1,4:1"Pour plus d'informations sur le répertoire warehouse, consultez la rubrique Exécution locale des tâches.
-
Cliquez sur Run pour exécuter la tâche SSSP localement.
RemarquePour les paramètres, reportez-vous au fichier conf/odps_config.ini du client MaxCompute. Les paramètres précédents sont couramment utilisés. La liste suivante décrit ces paramètres :
odps.runner.mode : la valeur doit être définie sur local. Ce paramètre est requis pour le débogage local.
odps.project.name : spécifie le projet actuel. Ce paramètre est requis.
odps.end.point : spécifie l'endpoint du service MaxCompute. Ce paramètre est facultatif. Si vous omettez ce paramètre, les tables et les ressources sont lues à partir du répertoire warehouse local. Une exception est levée si les données ou les métadonnées n'existent pas. Si vous spécifiez ce paramètre, le système tente d'abord de lire à partir du répertoire warehouse local. Si les données ou les métadonnées demandées n'existent pas, le système se rabat sur la lecture depuis MaxCompute.
odps.access.id : ID AccessKey pour la connexion au service MaxCompute. Ce paramètre est valide uniquement lorsque odps.end.point est spécifié.
odps.access.key : secret AccessKey pour la connexion au service MaxCompute. Ce paramètre est valide uniquement lorsque odps.end.point est spécifié.
odps.cache.resources : spécifie la liste des ressources à utiliser. Cela équivaut à l'option
-resourcesdans la commande JAR.odps.local.warehouse : chemin d'accès au répertoire warehouse local. Si ce paramètre n'est pas spécifié, le chemin par défaut est ./warehouse.
Voici la sortie de débogage lors de l'exécution locale de la tâche SSSP dans Eclipse.
Counters: 3 com.aliyun.odps.graph.local.COUNTER TASK_INPUT_BYTE=211 TASK_INPUT_RECORD=5 TASK_OUTPUT_BYTE=161 TASK_OUTPUT_RECORD=5 graph task finishRemarqueDans l'exemple précédent, le répertoire warehouse local doit contenir les tables sssp_in et sssp_out. Pour plus d'informations sur les tables sssp_in et sssp_out, consultez la rubrique Écriture d'un programme Graph.
Répertoire temporaire pour les tâches locales
Chaque fois que vous exécutez une session de débogage local, un répertoire temporaire est créé dans le répertoire de votre projet Eclipse. Un exemple de nom de répertoire temporaire est graph_20130816154834_240_5772. Il contient les sous-répertoires et fichiers suivants : counters (informations sur les compteurs), inputs (données d'entrée, telles que zhemin_test1.sssp_in), outputs (résultats de sortie, y compris le sous-répertoire _default_), resources (fichiers de ressources, y compris le sous-répertoire centers), superSteps (informations sur les supersteps) et le fichier de configuration de tâche job.xml.
Le répertoire temporaire d'une tâche Graph exécutée localement comprend les répertoires et fichiers suivants :
counters : contient les informations sur les compteurs générées pendant l'exécution de la tâche.
inputs : contient les données d'entrée de la tâche. Le système tente d'abord de récupérer les données depuis le répertoire warehouse local. Si les données sont introuvables et que le paramètre odps.end.point est défini, le système utilise le SDK MaxCompute pour lire les données depuis le serveur. Par défaut, un maximum de 10 enregistrements est lu pour chaque entrée input. Vous pouvez modifier cette limite en utilisant le paramètre
-Dodps.mapred.local.record.limit, mais la valeur ne peut pas dépasser 10 000.outputswarehouse : contient les données de sortie de la tâche. Une fois la tâche terminée, les données de résultat de ce répertoire écrasent la table correspondante dans le répertoire warehouse local.
resources : contient les ressources utilisées par la tâche. Comme pour les entrées, le système tente d'abord de récupérer les ressources depuis le répertoire warehouse local. Si les ressources sont introuvables, le système utilise le SDK MaxCompute pour les lire depuis le serveur, à condition que le paramètre odps.end.point soit défini.
job.xml : contient la configuration de la tâche.
superstep : stocke les informations de persistance pour chaque itération.
Pour afficher des journaux détaillés lors du débogage local, placez un fichier de configuration log4j nommé log4j.properties_odps_graph_local_debug dans le répertoire src.
Débogage sur cluster
Une fois le débogage local terminé, soumettez la tâche à un cluster pour test.
Procédure :
Configurez le client MaxCompute.
Utilisez la commande
add jar /path/work.jar -f;pour mettre à jour le package JAR.Exécutez la tâche à l'aide de la commande JAR et vérifiez le journal d'exécution ainsi que les données de résultat.
Pour plus d'informations sur l'exécution d'une tâche Graph sur un cluster, consultez la rubrique Écriture d'un programme Graph.
Optimisation des performances
Les éléments de configuration de tâche Graph suivants affectent les performances :
setSplitSize(long): taille de fractionnement pour la table d'entrée. Unité : Mo. La valeur doit être supérieure à 0. Valeur par défaut : 64.setNumWorkers(int): nombre de workers pour la tâche. Valeurs valides : [1, 1000]. Valeur par défaut : 1. Le nombre optimal de workers dépend de la taille d'entrée de la tâche en octets et de la valeursplitSize.setWorkerCPU(int): ressources CPU pour chaque worker. Une valeur de 100 représente un cœur CPU. Valeurs valides : [50, 800]. Valeur par défaut : 200.setWorkerMemory(int): ressources mémoire pour chaque worker. Unité : Mo. Valeurs valides : [256, 12288]. Valeur par défaut : 4096.setMaxIteration(int): nombre maximal d'itérations. Valeur par défaut : -1. Une valeur inférieure ou égale à 0 indique que le nombre maximal d'itérations n'est pas une condition de fin de tâche.setJobPriority(int): priorité de la tâche. Valeurs valides : [0, 9]. Valeur par défaut : 9. Une valeur plus élevée indique une priorité plus faible.
Recommandations générales pour l'optimisation :
Augmentez le nombre de workers en utilisant la méthode
setNumWorkers.Réduisez la taille de fractionnement en utilisant la méthode
setSplitSizepour accélérer le chargement des données.Augmentez les ressources CPU ou mémoire pour chaque worker.
Définissez le nombre maximal d'itérations. Pour les applications ne nécessitant pas une haute précision, réduisez le nombre d'itérations pour terminer la tâche plus rapidement.
Les API setNumWorkers et setSplitSize peuvent être utilisées conjointement pour améliorer la vitesse de chargement des données. Supposons que setNumWorkers est défini sur workerNum, setSplitSize est défini sur splitSize et que la taille totale d'entrée en octets est inputSize. Le nombre de fractions d'entrée est calculé comme suit : splitNum=inputSize/splitSize. La relation entre workerNum et splitNum est la suivante :
Scénario 1 : si
splitNumest égal àworkerNum, chaque worker est chargé de charger une fraction.Scénario 2 : si
splitNumest supérieur àworkerNum, chaque worker est chargé de charger une ou plusieurs fractions.Scénario 3 : si
splitNumest inférieur àworkerNum, chaque worker est chargé de charger zéro ou une fraction.
Par conséquent, ajustez workerNum et splitSize pour garantir que l'un des deux premiers scénarios est rempli afin d'accélérer le chargement des données. Pendant la phase d'itération, il vous suffit d'ajuster workerNum. Si vous définissez runtime partitioning sur False, utilisez setSplitSize pour contrôler le nombre de workers ou garantir que l'un des deux premiers scénarios est rempli. Si le troisième scénario se produit, certains workers n'auront aucune fraction attribuée. Pour éviter cela, vous pouvez utiliser la commande set odps.graph.split.size=<m>; set odps.graph.worker.num=<n>; avant la commande JAR. Cela revient à utiliser setNumWorkers et setSplitSize.
Un autre problème de performance courant est le déséquilibre des données (data skew). Dans la sortie des compteurs, cela se traduit par certains workers traitant significativement plus de sommets ou d'arêtes que d'autres. Le déséquilibre des données se produit généralement lorsque quelques clés correspondent à un nombre disproportionné de sommets, d'arêtes ou de messages. Ces clés sont attribuées à un petit nombre de workers, ce qui allonge leur temps d'exécution. Pour résoudre ce problème, utilisez l'une des méthodes suivantes :
-
Utilisez un Combiner pour agréger les messages de ces clés localement, ce qui réduit le nombre de messages envoyés.
Un Combiner réduit l'utilisation de la mémoire pour le stockage des messages et diminue le trafic réseau, raccourcissant ainsi le temps d'exécution global de la tâche.
-
Optimisez votre logique métier.
Pour les grands ensembles de données, les E/S disque peuvent dominer le temps de traitement. La réduction du volume de données améliore le débit et les performances :
Réduisez le volume de données d'entrée : pour certaines applications décisionnelles, le traitement d'un sous-ensemble échantillonné des données peut n'affecter que la précision du résultat, et non son exactitude globale. Dans ce cas, envisagez d'échantillonner les données avant de les importer dans la table d'entrée.
Évitez de lire les champs inutiles : la classe TableInfo du framework MaxCompute Graph vous permet de lire des colonnes spécifiques, transmises sous forme de tableau de noms de colonnes, au lieu de la table ou de la partition entière. Cela réduit également le volume de données d'entrée et améliore les performances de la tâche.
Packages JAR intégrés
Les packages JAR suivants sont chargés dans la JVM par défaut lorsque vous exécutez un programme Graph. Vous n'avez pas besoin de télécharger ces ressources ni de les inclure avec l'option -libjars dans votre commande.
commons-codec-1,3.jar
commons-io-2,0.1.jar
commons-lang-2,5.jar
commons-logging-1,0.4.jar
commons-logging-api-1,0.4.jar
guava-14,0.jar
json.jar
log4j-1,2.15.jar
slf4j-api-1,4.3.jar
slf4j-log4j12-1,4.3.jar
xmlenc-0,52.jar
Dans le classpath de la JVM, ces packages JAR intégrés sont prioritaires par rapport à vos packages JAR, ce qui peut entraîner des conflits de version. Par exemple, votre programme peut utiliser une fonction d'une classe dans commons-codec-1,5.jar qui n'existe pas dans commons-codec-1,3.jar. Si les fonctionnalités de la version 1,3 sont insuffisantes, vous devez attendre que MaxCompute soit mis à niveau vers une version plus récente.