Configurarea Spark pe YARN

Habr, salut! Ieri pe întâlnire dedicată lui Apache Spark, de la băieții de la Rambler&Co, au existat destul de multe întrebări din partea participanților legate de configurarea acestui instrument. Am decis să-i călcăm pe urme și să împărtășim experiența noastră. Subiectul nu este ușor – așa că vă invităm să împărtășiți experiența dumneavoastră în comentarii, poate înțelegem și folosim ceva greșit.

O mică introducere în modul în care folosim Spark. Avem un program de trei luni „Specialist în Big Data”, iar pe parcursul celui de-al doilea modul participanții noștri lucrează la acest instrument. În consecință, sarcina noastră, în calitate de organizatori, este să pregătim clusterul pentru utilizare într-un astfel de caz.

Particularitatea utilizării noastre este că numărul de persoane care lucrează simultan pe Spark poate fi egal cu întregul grup. De exemplu, la un seminar, când toată lumea încearcă ceva în același timp și repetă după profesorul nostru. Și asta nu este mult - uneori până la 40 de persoane. Probabil că nu există multe companii în lume care se confruntă cu un astfel de caz de utilizare.

În continuare, vă voi spune cum și de ce am selectat anumiți parametri de configurare.

Să începem de la bun început. Spark are 3 opțiuni pentru a rula pe un cluster: independent, folosind Mesos și folosind YARN. Am decis să alegem a treia variantă pentru că avea sens pentru noi. Avem deja un cluster Hadoop. Participanții noștri sunt deja bine familiarizați cu arhitectura sa. Să folosim YARN.

spark.master=yarn

Mai mult mai interesant. Fiecare dintre aceste 3 opțiuni de implementare are 2 opțiuni de implementare: client și cluster. Bazat documentație și diverse link-uri de pe Internet, putem concluziona că clientul este potrivit pentru lucrul interactiv - de exemplu, prin jupyter notebook, iar clusterul este mai potrivit pentru soluții de producție. În cazul nostru, ne-a interesat munca interactivă, prin urmare:

spark.deploy-mode=client

În general, de acum încolo Spark va funcționa cumva pe YARN, dar acest lucru nu a fost suficient pentru noi. Deoarece avem un program despre big data, uneori participanții nu au avut suficient din ceea ce s-a obținut în cadrul unei împărțiri uniforme a resurselor. Și apoi am găsit un lucru interesant - alocarea dinamică a resurselor. Pe scurt, ideea este aceasta: dacă aveți o sarcină dificilă și clusterul este liber (de exemplu, dimineața), atunci folosirea acestei opțiuni Spark vă poate oferi resurse suplimentare. Necesitatea se calculează acolo după o formulă vicleană. Nu vom intra în detalii - funcționează bine.

spark.dynamicAllocation.enabled=true

Am setat acest parametru, iar la pornire Spark s-a prăbușit și nu a pornit. Așa este, pentru că a trebuit să o citesc documentație cu mai multa grija. Afirmă că, pentru ca totul să fie ok, trebuie să activați și un parametru suplimentar.

spark.shuffle.service.enabled=true

De ce este nevoie? Când slujba noastră nu mai necesită atât de multe resurse, Spark ar trebui să le returneze în grupul comun. Etapa cea mai consumatoare de timp din aproape orice sarcină MapReduce este etapa de amestecare. Acest parametru vă permite să salvați datele care sunt generate în această etapă și să eliberați executanții în consecință. Iar executorul este procesul care calculează totul asupra muncitorului. Are un anumit număr de nuclee de procesor și o anumită cantitate de memorie.

Acest parametru a fost adăugat. Totul părea să funcționeze. A devenit evident că participanților li s-au oferit de fapt mai multe resurse atunci când au avut nevoie de ele. Dar a apărut o altă problemă - la un moment dat, alți participanți s-au trezit și au vrut să folosească Spark, dar totul era ocupat acolo și erau nemulțumiți. Ele pot fi înțelese. Am început să ne uităm la documentație. S-a dovedit că există o serie de alți parametri care pot fi utilizați pentru a influența procesul. De exemplu, dacă executorul se află în modul standby, după ce timp pot fi preluate resurse de la acesta?

spark.dynamicAllocation.executorIdleTimeout=120s

În cazul nostru, dacă executorii dvs. nu fac nimic timp de două minute, atunci vă rugăm să-i returnați la bazinul comun. Dar acest parametru nu a fost întotdeauna suficient. Era clar că persoana respectivă nu făcuse nimic de mult timp, iar resursele nu erau eliberate. S-a dovedit că există și un parametru special - după ce oră să selectăm executanții care conțin date în cache. În mod implicit, acest parametru era infinit! Am corectat-o.

spark.dynamicAllocation.cachedExecutorIdleTimeout=600s

Adică, dacă executorii tăi nu fac nimic timp de 5 minute, dă-i la bazinul comun. În acest mod, viteza de eliberare și emitere a resurselor pentru un număr mare de utilizatori a devenit decentă. Cantitatea de nemulțumire a scăzut. Dar am decis să mergem mai departe și să limităm numărul maxim de executanți per aplicație - în esență per participant la program.

spark.dynamicAllocation.maxExecutors=19

Acum, desigur, există oameni nemulțumiți de cealaltă parte - „clusterul este inactiv și am doar 19 executori”, dar ce poți face? Avem nevoie de un echilibru corect. Nu poți să-i faci pe toți fericiți.

Și încă o mică poveste legată de specificul cazului nostru. Cumva, mai multe persoane au întârziat la o lecție practică și, din anumite motive, Spark nu a început pentru ei. Ne-am uitat la cantitatea de resurse gratuite - se pare că există. Spark ar trebui să pornească. Din fericire, până atunci documentația fusese deja adăugată la subcortex undeva și ne-am amintit că atunci când este lansat, Spark caută un port pe care să pornească. Dacă primul port din gamă este ocupat, se mută la următorul în ordine. Dacă este gratuit, captează. Și există un parametru care indică numărul maxim de încercări pentru aceasta. Valoarea implicită este 16. Numărul este mai mic decât numărul de persoane din grupul nostru în clasă. În consecință, după 16 încercări, Spark a renunțat și a spus că nu pot începe. Am corectat acest parametru.

spark.port.maxRetries=50

În continuare, vă voi spune despre câteva setări care nu sunt foarte legate de specificul cazului nostru.

Pentru a porni Spark mai repede, este recomandat să arhivați folderul jars aflat în directorul principal SPARK_HOME și să îl puneți pe HDFS. Atunci nu va pierde timpul încărcând aceste jarnik-uri de către muncitori.

spark.yarn.archive=hdfs:///tmp/spark-archive.zip

De asemenea, se recomandă utilizarea kryo ca serializator pentru o funcționare mai rapidă. Este mai optimizat decât cel implicit.

spark.serializer=org.apache.spark.serializer.KryoSerializer

Și există, de asemenea, o problemă de lungă durată cu Spark, care se blochează adesea din memorie. Adesea acest lucru se întâmplă în momentul în care lucrătorii au calculat totul și trimit rezultatul șoferului. Am mărit acest parametru pentru noi înșine. În mod implicit, este de 1 GB, noi l-am făcut 3.

spark.driver.maxResultSize=3072

Și în sfârșit, ca desert. Cum se actualizează Spark la versiunea 2.1 pe distribuția HortonWorks - HDP 2.5.3.0. Această versiune de HDP conține o versiune preinstalată 2.0, dar am decis odată pentru noi înșine că Spark se dezvoltă destul de activ, iar fiecare versiune nouă remediază unele erori și oferă caracteristici suplimentare, inclusiv pentru API-ul python, așa că am decis ce trebuie să facem fi făcut este o actualizare.

Am descărcat versiunea de pe site-ul oficial pentru Hadoop 2.7. Dezarhivați-l și puneți-l în folderul HDP. Am instalat legăturile simbolice după cum este necesar. Îl lansăm - nu pornește. Scrie o eroare foarte neclară.

java.lang.NoClassDefFoundError: com/sun/jersey/api/client/config/ClientConfig

După ce am căutat pe google, am aflat că Spark a decis să nu aștepte până când s-a născut Hadoop și a decis să folosească noua versiune a tricoului. Ei înșiși se ceartă între ei despre acest subiect în JIRA. Soluția a fost descărcarea Tricou versiunea 1.17.1. Plasați-l în folderul jars din SPARK_HOME, arhivați-l din nou și încărcați-l în HDFS.

Am ocolit această eroare, dar a apărut una nouă și destul de simplificată.

org.apache.spark.SparkException: Yarn application has already ended! It might have been killed or unable to launch application master

În același timp, încercăm să rulăm versiunea 2.0 - totul este ok. Încercați să ghiciți ce se întâmplă. Ne-am uitat în jurnalele acestei aplicații și am văzut ceva de genul acesta:

/usr/hdp/${hdp.version}/hadoop/lib/hadoop-lzo-0.6.0.${hdp.version}.jar

În general, din anumite motive, hdp.version nu s-a rezolvat. După ce am căutat pe google, am găsit o soluție. Trebuie să accesați setările YARN în Ambari și să adăugați un parametru acolo la site-ul personalizat de fire:

hdp.version=2.5.3.0-37

Această magie a ajutat, iar Spark a decolat. Am testat mai multe dintre laptopurile noastre jupyter. Totul merge. Suntem pregătiți pentru prima lecție Spark de sâmbătă (mâine)!

DUP. În timpul lecției, a ieșit la iveală o altă problemă. La un moment dat, YARN a încetat să ofere containere pentru Spark. În YARN a fost necesar să se corecteze parametrul, care implicit era 0.2:

yarn.scheduler.capacity.maximum-am-resource-percent=0.8

Adică, doar 20% din resurse au participat la distribuirea resurselor. După modificarea parametrilor, am reîncărcat YARN. Problema a fost rezolvată și restul participanților au putut, de asemenea, să ruleze contextul scânteie.

Sursa: www.habr.com

Adauga un comentariu