Konfigurimi i Spark në YARN

Përshëndetje, Habr! Ddje në mitapin e dedikuar Apache Spark, nga djemtë e Rambler&Co, kishte shumë pyetje nga pjesëmarrësit në lidhje me konfigurimin e këtij instrumenti. Vendosëm të ndanim përvojën tonë pas tij. Tema nuk është e thjeshtë — prandaj, ju lutemi ndihmoni duke ndarë përvojën tuaj në komente, ndoshta ne gjithashtu nuk kuptojmë ndonjë gjë siç duhet dhe përdorim.

Një hyrje e vogël — si e përdorim Spark. Ne kemi një program tre-mujor “Specialist për të dhëna të mëdha”, dhe gjatë modulit të dytë, pjesëmarrësit tanë punojnë me këtë instrument. Si organizatorë, detyra jonë është të përgatisim një klaster për përdorim në këtë rast.

Veçoria e përdorimit tonë është se numri i njerëzve që punojnë në mënyrë të njëkohshme me Spark mund të jetë i barabartë me të gjithë grupin. Për shembull, në seminar, kur të gjithë provojnë diçka në një kohë dhe përsëritin pas mësuesit tonë. Dhe kjo është jo pak — deri në 40 njerëz ndonjëherë. Ndoshta nuk ka shumë kompani në botë që përballen me një skenar përdorimi të tillë.

Më tej do të flas se si dhe pse përzgjedhëm parametrat e caktuar të konfigurimit.

Të fillojmë nga fillimi. Spark ka 3 mundësi për të punuar në klaster: standalone, duke përdorur Mesos dhe duke përdorur YARN. Ne vendosëm të zgjidhim opsionin e tretë, sepse për ne ishte logjik.

spark.master=yarn

Më pas bëhet më interesante. Çdo një nga këto 3 variante të vendosjes ka 2 variante të shkarkimit: client dhe cluster. Duke u bazuar në dokumentacionin dhe lidhjet e ndryshme në internet, mund të arrijmë në përfundimin se client është i përshtatshëm për punë interaktive — për shembull, përmes jupyter notebook, ndërsa cluster është më i përshtatshëm për zgjidhje produksioni. Në rastin tonë, na interesonte puna interaktive, kështu që:

spark.deploy-mode=client

Në të vërtetë nga ky moment, Spark do të funksionojë në YARN, por kjo nuk ishte e mjaftueshme për ne. Duke qenë se kemi një program për të dhëna të mëdha, për disa pjesëmarrës ndonjëherë u mungonin burimet që fitoheshin nga ndarja e rregullt të tyre. Dhe këtu gjetëm një gjë interesante — alokimin dinamik të burimeve. Në shprehje të thjeshtë, nëse keni një detyrë të rëndë dhe klasteri është i lirë (për shembull, mëngjesin), atëherë me këtë opsion, Spark mund t'ju ofrojë burime shtesë. Nevojat llogariten sipas një formule të zgjuar. Nuk do të hyjmë në detaje — punon mirë.

spark.dynamicAllocation.enabled=true

E vendosëm këtë parametër, dhe kur e filluam Spark, ai u ankuar dhe nuk nisi. E drejtë, sepse duhej të lexohej dokumentacion më me vëmendje. Atje thotë se për ta pasur gjithçka në rregull, duhet të aktivizoni një parametër shtesë.

spark.shuffle.service.enabled=true

Pse është e nevojshme? Kur puna jonë nuk kërkon më kaq shumë burime, Spark duhet t'i kthejë ato në rezervë të përgjithshme. Faza më e punës intensiven në çdo detyrë MapReduce është faza Shuffle. Ky parametër lejon që të ruhen të dhënat që krijohen në këtë fazë dhe për pasojë të çliron executorët. Një executor është një proces që llogarit gjithçka në punëtorë. Ai ka një numër të caktuar bërthama procesori dhe një sasi të caktuar memories.

E vendosëm këtë parametër. Gjithçka dukej se po funksiononte. U vërejt se pjesëmarrësit merrnin më shumë burime kur u nevoiteshin. Por ndodhi një problem tjetër — në një moment, pjesëmarrësit e tjerë u zgjuan dhe gjithashtu donin të përdornin Spark, por e gjithë kapaciteti ishte i zënë, dhe ata ishin të pakënaqur. Mund të kuptohen. Filluam të shikojmë dokumentacionin. Atje doli se kishte disa parametra të tjerë, me të cilët mund të ndikojmë në proces. Për shembull, nëse një executor është në modalitetin e zgjedhjes — pas sa kohe mund t'i merret burimet?

spark.dynamicAllocation.executorIdleTimeout=120s

Në rastin tonë — nëse ekzekutorët tuaj nuk bëjnë asgjë për dy minuta, ju lutemi, kthejini ata në pool-in e përgjithshëm. Por as ky parametër nuk ishte gjithmonë i mjaftueshëm. Ishte e dukshme që një njeri nuk po bënte asgjë për një kohë të gjatë, por burimet nuk po liroheshin. U zbulua se kishte edhe një parametër të veçantë — pas sa kohe të merreshin ekzekutorët që përmbanin të dhëna të ruajtura në cache. Në default, ky parametër ishte vendosur — pafundësi! Ne e ndryshuam atë.

spark.dynamicAllocation.cachedExecutorIdleTimeout=600s

Pra, nëse për 5 minuta ekzekutorët tuaj nuk bëjnë asgjë, ktheni ata në pool-in e përgjithshëm. Në këtë mënyrë, shpejtësia e lirimit dhe ndarjes së burimeve për një numër të madh përdoruesish u bë e kënaqshme. Numri i pakënaqësive u reduktua. Por ne vendosëm të shkojmë përpara dhe të kufizojmë numrin maksimal të ekzekutorëve për një aplikacion — në thelb për një pjesëmarrës në program.

spark.dynamicAllocation.maxExecutors=19

Tani, sigurisht, kanë dalë të pakënaqur nga ana tjetër — “klusteri është i papunë, dhe unë kam vetëm 19 ekzekutorë”, por çfarë mund të bëjmë — na nevojitet një balancim i duhur. Të gjithë të bëhen të lumtur nuk do të jetë e mundur.

Dhe një histori e vogël tjetër, e lidhur me specifikën e rastit tonë. Disa njerëz mbetën pas në një praktikë, dhe për një arsye, Spark nuk nisi. Ne shikojmë numrin e burimeve të lira — duket se ka. Spark duhet të nisë. Fatmirësisht, në ato momente dokumentacioni tashmë ishte regjistruar në nënndërgjegje, dhe ne e kujtuam se kur Spark nis, ai kërkon një port për të nisur. Nëse porta e parë nga diapazoni është e zënë, ai kalon në portin tjetër në rend. Nëse ai është i lirë, ai e merr. Dhe ka një parametr që tregon numrin maksimal të përpjekjeve për këtë. Në default — është 16. Numri është më i vogël se njerëzit në grupin tonë në seancë. Si rezultat, pas 16 përpjekjesh, Spark dorëzonte këtë punë dhe thoshte se nuk mund të nisi. Ne e kemi rregulluar këtë parametr.

spark.port.maxRetries=50

Më pas do t'ju tregoj për disa konfigurime, të cilat nuk janë shumë të lidhura me specifikën e rastit tonë.

Për një nisje më të shpejtë të Spark, ka një rekomandim që folderin jars, që ndodhet në direktorinë shtëpiake SPARK_HOME, ta kompresoni dhe ta vendosni në HDFS. Atëherë ai nuk do të humbasë kohë në shkarkimin e këtyre jar-ëve në punëtorë.

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

Po gjithashtu, për një punë më të shpejtë, rekomandohet të përdoret kryo si serializues. Ai është më i optimizuar se ai që është nga parazgjedhja.

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

Dhe ka një problem të vjetër me Spark, se shpesh dështon për shkak të memory. Kjo ndodh shpesh në momentin kur punëtorët kanë përfunduar gjithçka dhe dërgojnë rezultatin në drejtues. Ne e kemi rritur këtë parametër. Nga parazgjedhja është 1GB, ne bëmë — 3.

spark.driver.maxResultSize=3072

Dhe e fundit, si një ëmbëlsirë. Si të përmirësoni Spark në versionin 2.1 mbi distribucionin HortonWorks — HDP 2.5.3.0. Ky version i HDP përmban versionin e parainstaluar 2.0, por një herë vendosëm se Spark po zhvillohet mjaft aktivisht, dhe çdo version i ri rregullon disa gabime dhe gjithashtu ofron mundësi të tjera, përfshirë për API-në python, prandaj vendosëm se duhet të bënim azhurnim.

Kemi shkarkuar versionin nga faqja zyrtare për Hadoop 2.7. E kemi zgjidhur, e kemi futur në dosjen me HDP. Vendosëm lidhjet siç duhet. E nisim — nuk fillon. Shkruan një gabim shumë të paqartë.

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

Pas kërkimeve në Google, zbuluam se Spark vendosi të mos presë derisa Hadoop të ndihmojë dhe vendosi të përdorë versionin e ri të jersey. Ata vetë diskutuan për këtë temë në JIRA. Çelja ishte — shkarko jersey versioni 1.17.1. E vendosëm këtë në dosjen jars në SPARK_HOME, përsëri bëmë zip dhe e dërguam në HDFS.

Këtë gabim e kaluam, por u shfaq një e re dhe mjaft e paqartë.

org.apache.spark.SparkException: Yarn application has already ended! Mund të jetë mbyllur ose nuk ka mundur të nisë master-in e aplikacionit.

Ndërkohë, provojmë të nisim versionin 2.0 — gjithçka është në rregull. E kupto si duket. Ne u ngjitëm në logjet e këtij aplikacioni dhe pashë diçka të tillë:

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

Në përgjithësi, për disa arsye hdp.version nuk u zgjidh. Pas kërkimeve, gjetëm zgjidhjen. Duhet të hyjmë në Ambari në cilësimet YARN dhe të shtojmë atje parametrin në yarn-site-un e personalizuar:

hdp.version=2.5.3.0-37

Kjo magji ndihmoi, dhe Spark fluturoi. E provuam disa nga jupyter-notebook-et tona. Gjithçka funksionon. Jemi gati për mbledhjen e parë për Spark të shtunën (tashmë nesër)!

UPD. Në mbledhje doli një problem tjetër. Në një moment YARN ndaloi së dhëni kontejnerë për Spark. Në YARN ne patëm nevojë të rregullojmë parametrin, i cili për defolt ishte 0.2:

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

Pra t'u thënë, vetëm 20% e burimeve ishin të angazhuara në shpërndarjen e burimeve. Duke ndryshuar parametrat, ne riluam YARN. Problemi u zgjidh dhe pjesëmarrësit e tjerë gjithashtu mundën të nisnin kontekstin e spark.

Burimi: habr.com

Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS 🔥 Blini hostim të besueshëm për faqe interneti me mbrojtje DDoS, serverë VPS VDS - ProHoster