"La mia libreria è nel percorso di classe ma ricevo ancora un'eccezione Classe non trovata in un lavoro MapReduce" – Se hai questo problema, questo blog è per te.
Java richiede che le classi di terze parti e definite dall'utente siano sul "–classpath della riga di comando ” quando viene avviata la JVM. Lo script della shell del wrapper `hadoop` fa esattamente questo per te costruendo il classpath dalle librerie principali che si trovano in /usr/lib/hadoop-0.20/ e /usr/lib/hadoop-0.20/lib/ directory. Tuttavia, con MapReduce i tentativi di attività del tuo lavoro vengono eseguiti su nodi remoti. Come si dice a una macchina remota di includere classi di terze parti e definite dall'utente?
I lavori MapReduce vengono eseguiti in JVM separate su TaskTracker e talvolta è necessario utilizzare librerie di terze parti nei tentativi di mappare/ridurre. Ad esempio, potresti voler accedere a HBase dalle tue attività mappa. Un modo per farlo è quello di impacchettare ogni classe utilizzata nel JAR inviabile. Dovrai decomprimere il hbase-.jar
originale e riconfeziona tutte le classi nel tuo vaso Hadoop inviabile. Non bene. Non farlo:i problemi di compatibilità della versione ti morderanno prima o poi.
Esistono modi migliori per fare lo stesso mettendo il tuo jar nella cache distribuita o installando l'intero JAR sui nodi Hadoop e comunicando a TaskTrackers la loro posizione.
1. Includere il JAR in "-libjars ” opzione della riga di comando del comando `hadoop jar …`. Il jar verrà inserito nella cache distribuita e sarà reso disponibile a tutti i tentativi di attività del lavoro. Più specificamente, troverai il JAR in uno dei ${mapred.local.dir}/taskTracker/archive/${user.name}/distcache/… sottodirectory sui nodi locali. Il vantaggio della cache distribuita è che il tuo jar potrebbe essere ancora lì alla tua prossima esecuzione del programma (almeno in teoria:i file dovrebbero essere espulsi dalla cache distribuita solo quando superano il limite soft definito da local.cache .dimensione variabile di configurazione, l'impostazione predefinita è 10 GB, ma il tuo chilometraggio effettivo può variare in particolare con i più recenti miglioramenti della sicurezza). Hadoop tiene traccia delle modifiche ai file di cache distribuiti esaminando il timestamp di modifica.
*Aggiornamento al post:tieni presente che gli elementi 2 e 3 di seguito sono obsoleti a partire da CDH4 e non saranno più supportati a partire da CDH5.
2. Includere il JAR di riferimento nella sottodirectory lib del JAR inviabile:un lavoro MapReduce decomprimerà il JAR da questa sottodirectory in ${mapred.local.dir}/taskTracker/${user.name}/jobcache/$ jobid/jars sui nodi TaskTracker e punta le tue attività a questa directory per rendere il JAR disponibile per il tuo codice. Se i JAR sono piccoli, cambiali spesso e sono specifici del lavoro, questo è il metodo preferito.
3. Infine, puoi installare il JAR sui nodi del cluster. Il modo più semplice è posizionare il JAR in $HADOOP_HOME/lib directory poiché tutto da questa directory è incluso all'avvio di un demone Hadoop. Tuttavia, poiché sai che solo i TaskTracker avranno bisogno di questi nel nuovo JAR, un modo migliore è modificare l'opzione HADOOP_TASKTRACKER_OPTS nel file di configurazione hadoop-env.sh. Questo metodo è preferito se il JAR è legato al codice in esecuzione sui nodi, come HBase.
HADOOP_TASKTRACKER_OPTS="-classpath<colon-separated-paths-to-your-jars>"
Riavvia i TastTracker quando hai finito. Non dimenticare di aggiornare il jar quando cambia il software sottostante.
Tutte le opzioni precedenti influiscono solo sul codice in esecuzione sui nodi distribuiti. Se il codice che avvia il lavoro Hadoop utilizza la stessa libreria, è necessario includere anche il JAR nella variabile di ambiente HADOOP_CLASSPATH:
HADOOP_CLASSPATH="<colon-separated-paths-to-your-jars>"
Nota che a partire da Java 1.6 classpath può puntare a directory come "/path/to/your/jars/* ” che raccoglierà tutti i JAR dalla directory specificata.
Gli stessi principi guida si applicano alle librerie di codice native che devono essere eseguite sui nodi (pipe JNI o C++). Puoi metterli nella cache distribuita con i "-files ”, includerli nei file di archivio specificati con “-archives ” o installarli sui nodi del cluster. Se il linker della libreria dinamica è configurato correttamente, il codice nativo dovrebbe essere reso disponibile per i tentativi di attività. Puoi anche modificare l'ambiente dei tentativi di attività in esecuzione del lavoro in modo esplicito specificando le variabili JAVA_LIBRARY_PATH o LD_LIBRARY_PATH:
hadoop jar <your jar> [main class] -D mapred.child.env="LD_LIBRARY_PATH=/path/to/your/libs" ...