sql >> Database >  >> NoSQL >> HBase

Procedure:bibliotheken van derden opnemen in uw MapReduce-taak

"Mijn bibliotheek bevindt zich in het klassenpad, maar ik krijg nog steeds een Class Not Found-uitzondering in een MapReduce-taak" - Als je dit probleem hebt, is deze blog iets voor jou.

Java vereist dat klassen van derden en door de gebruiker gedefinieerde klassen zich op het "–classpath van de opdrachtregel bevinden ” optie wanneer de JVM wordt gestart. Het `hadoop` wrapper-shellscript doet precies dit voor u door het klassenpad te bouwen vanuit de kernbibliotheken in /usr/lib/hadoop-0.20/ en /usr/lib/hadoop-0.20/lib/ mappen. Met MapReduce worden de taakpogingen van uw taak echter uitgevoerd op externe knooppunten. Hoe vertel je een externe machine om klassen van derden en door de gebruiker gedefinieerde klassen op te nemen?

MapReduce-taken worden uitgevoerd in afzonderlijke JVM's op TaskTrackers en soms moet u bibliotheken van derden gebruiken bij de kaart-/reductietaakpogingen. U wilt bijvoorbeeld vanuit uw kaarttaken toegang krijgen tot HBase. Een manier om dit te doen is om elke klasse die wordt gebruikt in de indienbare JAR te verpakken. U moet de originele hbase-.jar . uitpakken en verpak alle klassen opnieuw in uw in te dienen Hadoop-pot. Niet goed. Doe dit niet:de compatibiliteitsproblemen van de versie zullen u vroeg of laat bijten.

Er zijn betere manieren om hetzelfde te doen door ofwel uw jar in een gedistribueerde cache te plaatsen of de hele JAR op de Hadoop-knooppunten te installeren en TaskTrackers over hun locatie te vertellen.

1. Voeg de JAR toe aan de “-libjars ” opdrachtregeloptie van de opdracht `hadoop jar …`. De pot wordt in de gedistribueerde cache geplaatst en wordt beschikbaar gemaakt voor alle taakpogingen van de taak. Meer specifiek vindt u de JAR in een van de ${mapred.local.dir}/taskTracker/archive/${user.name}/distcache/… submappen op lokale knooppunten. Het voordeel van de gedistribueerde cache is dat je jar er nog steeds kan zijn bij je volgende programma-uitvoering (althans in theorie:de bestanden moeten alleen uit de gedistribueerde cache worden gegooid als ze de zachte limiet overschrijden die is gedefinieerd door de local.cache .maat configuratievariabele, standaard ingesteld op 10 GB, maar uw werkelijke aantal kilometers kan variëren, vooral met de nieuwste beveiligingsverbeteringen). Hadoop houdt de wijzigingen in de gedistribueerde cachebestanden bij door hun wijzigingstijdstempel te onderzoeken.

*Update om te posten:Houd er rekening mee dat onderstaande items 2 en 3 niet meer worden ondersteund vanaf CDH4 en niet langer worden ondersteund vanaf CDH5.

2. Neem de JAR waarnaar wordt verwezen op in de lib-submap van de in te dienen JAR:een MapReduce-taak zal de JAR uit deze submap uitpakken in ${mapred.local.dir}/taskTracker/${user.name}/jobcache/$ jobid/potten op de TaskTracker-knooppunten en verwijs uw taken naar deze map om de JAR beschikbaar te maken voor uw code. Als de JAR's klein zijn, vaak veranderen en functiespecifiek zijn, heeft dit de voorkeursmethode.

3. Ten slotte kunt u de JAR op de clusterknooppunten installeren. De gemakkelijkste manier is om de JAR in $HADOOP_HOME/lib . te plaatsen directory omdat alles uit deze directory wordt opgenomen wanneer een Hadoop-daemon wordt gestart. Omdat je echter weet dat alleen TaskTrackers deze nodig hebben in de nieuwe JAR, is het een betere manier om de HADOOP_TASKTRACKER_OPTS optie in het hadoop-env.sh configuratiebestand te wijzigen. Deze methode heeft de voorkeur als de JAR is gekoppeld aan de code die op de knooppunten wordt uitgevoerd, zoals HBase.

HADOOP_TASKTRACKER_OPTS="-classpath<colon-separated-paths-to-your-jars>"

Start de TastTrackers opnieuw als u klaar bent. Vergeet niet om de jar bij te werken wanneer de onderliggende software verandert.

Alle bovenstaande opties zijn alleen van invloed op de code die op de gedistribueerde knooppunten wordt uitgevoerd. Als uw code die de Hadoop-taak start dezelfde bibliotheek gebruikt, moet u de JAR ook opnemen in de HADOOP_CLASSPATH-omgevingsvariabele:

HADOOP_CLASSPATH="<colon-separated-paths-to-your-jars>"

Merk op dat te beginnen met Java 1.6 classpath kan verwijzen naar mappen zoals "/path/to/your/jars/* ” die alle JAR's uit de opgegeven map zal ophalen.

Dezelfde leidende principes zijn van toepassing op native codebibliotheken die op de knooppunten moeten worden uitgevoerd (JNI- of C++-pipes). U kunt ze in de gedistribueerde cache plaatsen met de "-bestanden ” opties, voeg ze toe aan archiefbestanden die gespecificeerd zijn met de “-archives ” optie, of installeer ze op de clusterknooppunten. Als de dynamische bibliotheeklinker correct is geconfigureerd, moet de native code beschikbaar worden gemaakt voor uw taakpogingen. U kunt de omgeving van de actieve taakpogingen van de taak ook expliciet wijzigen door JAVA_LIBRARY_PATH- of LD_LIBRARY_PATH-variabelen op te geven:

hadoop jar <your jar> [main class]
      -D mapred.child.env="LD_LIBRARY_PATH=/path/to/your/libs" ...

  1. Zijn er redenen waarom ik ObjectId's wel/niet zou moeten gebruiken in mijn RESTful url's

  2. node redis, variabelen worden gedeeld tussen clients?

  3. mongoDB upsert op array

  4. Redis SYNC en EXEC