„Moje knihovna je v cestě ke třídě, ale v úloze MapReduce stále dostávám výjimku Class Not Found“ – Pokud máte tento problém, tento blog je pro vás.
Java vyžaduje, aby třídy třetích stran a uživatelem definované třídy byly na příkazovém řádku „–classpath ” při spuštění JVM. Skript shellu `hadoop` to dělá přesně za vás tím, že vytváří classpath z hlavních knihoven umístěných v /usr/lib/hadoop-0.20/ a /usr/lib/hadoop-0.20/lib/ adresáře. S MapReduce se však pokusy o úlohu vaší úlohy provádějí na vzdálených uzlech. Jak řeknete vzdálenému počítači, aby zahrnoval třídy třetích stran a uživatelem definované třídy?
Úlohy MapReduce se spouštějí v samostatných JVM na TaskTrackers a někdy je potřeba použít knihovny třetích stran v pokusech o mapování/redukování úloh. Můžete například chtít přistupovat k HBase z vašich mapových úloh. Jedním ze způsobů, jak toho dosáhnout, je zabalit každou třídu použitou v předložitelném JAR. Budete muset rozbalit původní soubor hbase-.jar
a znovu zabalte všechny třídy ve vaší předložitelné nádobě Hadoop. Špatný. Nedělejte to:Problémy s kompatibilitou verzí vás dříve nebo později překousnou.
Existují lepší způsoby, jak udělat totéž tak, že buď vložíte svůj jar do distribuované mezipaměti, nebo nainstalujete celý JAR na uzly Hadoop a řeknete TaskTrackerům o jejich umístění.
1. Zahrňte JAR do „-libjars ” možnost příkazového řádku příkazu `hadoop jar …`. Sklenice bude umístěna do distribuované mezipaměti a bude zpřístupněna všem pokusům o úlohu úlohy. Konkrétněji najdete JAR v jednom z ${mapred.local.dir}/taskTracker/archive/${user.name}/distcache/… podadresáře na lokálních uzlech. Výhodou distribuované mezipaměti je, že při příštím spuštění programu může být váš jar stále k dispozici (alespoň teoreticky:Soubory by měly být vyhozeny z distribuované mezipaměti pouze tehdy, když překročí měkký limit definovaný local.cache .velikost konfigurační proměnná, výchozí hodnota je 10 GB, ale váš skutečný počet najetých kilometrů se může lišit zejména s nejnovějšími vylepšeními zabezpečení). Hadoop sleduje změny v distribuovaných souborech mezipaměti zkoumáním jejich časového razítka.
*Aktualizace příspěvku:Upozorňujeme, že položky 2 a 3 níže jsou počínaje CDH4 zastaralé a počínaje CDH5 již nebudou podporovány.
2. Zahrňte odkazovaný JAR do podadresáře lib předkládacího JAR:Úloha MapReduce rozbalí JAR z tohoto podadresáře do ${mapred.local.dir}/taskTracker/${user.name}/jobcache/$ jobid/jars na uzlech TaskTracker a nasměrujte své úkoly do tohoto adresáře, aby byl JAR dostupný pro váš kód. Pokud jsou JAR malé, často se mění a jsou specifické pro práci, je to preferovaná metoda.
3. Nakonec můžete nainstalovat JAR na uzly clusteru. Nejjednodušší způsob je umístit JAR do $HADOOP_HOME/lib adresář, protože vše z tohoto adresáře je zahrnuto při spuštění démona Hadoop. Protože však víte, že tyto nové JAR budou potřebovat pouze TaskTrackery, lepší způsob je upravit volbu HADOOP_TASKTRACKER_OPTS v konfiguračním souboru hadoop-env.sh. Tato metoda je preferována, pokud je JAR svázán s kódem běžícím na uzlech, jako je HBase.
HADOOP_TASKTRACKER_OPTS="-classpath<colon-separated-paths-to-your-jars>"
Po dokončení restartujte TastTrackers. Nezapomeňte aktualizovat jar, když se změní základní software.
Všechny výše uvedené možnosti ovlivňují pouze kód běžící na distribuovaných uzlech. Pokud váš kód, který spouští úlohu Hadoop, používá stejnou knihovnu, musíte také zahrnout JAR do proměnné prostředí HADOOP_CLASSPATH:
HADOOP_CLASSPATH="<colon-separated-paths-to-your-jars>"
Všimněte si, že počínaje Java 1.6 classpath může ukazovat na adresáře jako „/cesta/k/vašemu/jaru/* ” který vybere všechny JAR z daného adresáře.
Stejné hlavní zásady platí pro knihovny nativního kódu, které je třeba spouštět na uzlech (potrubí JNI nebo C++). Můžete je uložit do distribuované mezipaměti pomocí „-souborů “, zahrňte je do archivních souborů určených pomocí „-archives ” nebo je nainstalujte na uzly clusteru. Pokud je linker dynamických knihoven správně nakonfigurován, nativní kód by měl být zpřístupněn vašim pokusům o úlohu. Můžete také upravit prostředí pokusů o spuštěnou úlohu explicitně zadáním proměnných JAVA_LIBRARY_PATH nebo LD_LIBRARY_PATH:
hadoop jar <your jar> [main class] -D mapred.child.env="LD_LIBRARY_PATH=/path/to/your/libs" ...