Zdravo, Habr! Juče na , od ekipe iz Rambler&Co, bilo je prilično mnogo pitanja od učesnika koja su se odnosila na konfiguraciju ovog alata. Odlučili smo podeliti svoje iskustvo. Tema nije jednostavna — zato pozivamo i vas da podelite svoje iskustvo u komentarima, možda i mi nešto ne razumemo ili koristimo na pogrešan način.
Mala uvodna reč — kako mi koristimo Spark. Imamo tromesečni program , i tokom drugog modula naši učesnici rade na ovom alatu. Naša obaveza kao organizatora je da pripremimo klaster za korišćenje u okviru takvog slučaja.
Specifičnost našeg korišćenja leži u tome da broj ljudi koji simultano radi na Sparku može biti jednak celoj grupi. Na primer, na seminaru, kada svi istovremeno nešto isprobavaju i ponavljaju za našim predavačem. A to je ponekad čak do 40 osoba. Verovatno, nema mnogo firmi u svetu koje se susreću sa takvim scenarijem korišćenja.
Dalje ću objasniti kako i zašto smo birali određene parametre konfiguracije.
Počnimo od samog početka. Spark može raditi na klasteru u 3 režima: standalone, koristeći Mesos i koristeći YARN. Odlučili smo se za treću opciju, jer nam je ona delovala logičnije. Već imamo Hadoop klaster. Naši učesnici su već dobro upoznati sa njegovom arhitekturom. Hajde da koristimo YARN.
spark.master=yarnDalje postaje zanimljivije. Svaka od ove 3 opcije implementacije ima 2 opcije rasporeda: client i cluster. S obzirom na različite izvore na internetu, može se zaključiti da je client više prikladan za interaktivni rad — na primer, preko Jupyter Notebook-a, dok je cluster bolje rešenje za produkcijska okruženja. U našem slučaju nas je interesovao interaktivni rad, tako da:
spark.deploy-mode=clientSplošno gledano, od ovog trenutka Spark će već raditi na YARN-u, ali to nam nije bilo dovoljno. Budući da imamo program vezan za velike podatke, često učesnicima nije bilo dovoljno onoga što se dobijalo u okviru ravnomernog dodeljivanja resursa. I tu smo pronašli zanimljivu stvar — dinamičko dodeljivanje resursa. Ukratko, suština je sledeća: ako imate zahtevnu zadatak i klaster je slobodan (na primer, ujutro), uz pomoć ove opcije, Spark vam može dodeliti dodatne resurse. Potrebna potreba se računa po složenoj formuli. Nećemo ulaziti u pojedinosti — ona prilično dobro funkcioniše.
spark.dynamicAllocation.enabled=truePostavili smo ovaj parametar i prilikom pokretanja Sparka došlo je do greške i nije se pokrenuo. U pravu ste, jer je trebalo pažljivije pročitati To je označeno, da bi sve bilo u redu, potrebno je takođe uključiti dodatni parametar.
spark.shuffle.service.enabled=trueZašto je on potreban? Kada naš posao više ne zahteva toliki broj resursa, Spark bi trebao da vrati resurse u zajedničku stazu. Najtromljivija faza u gotovo svakoj MapReduce zadatku je faza Shuffle. Ovaj parametar omogućava čuvanje podataka koji nastaju u ovoj fazi i oslobađanje executora. A executor je proces koji sve obrađuje na radniku. Ima određeni broj procesorskih jezgara i određeni broj memorije.
Dodali smo ovaj parametar. Sve kao da je počelo da funkcioniše. Postalo je primetno da učesnicima stvarno dodeljuju više resursa kada im je to bilo potrebno. Ali javio se drugi problem — u nekom trenutku ostali učesnici su se probudili i takođe su želeli da koriste Spark, ali je sve bilo zauzeto, i nisu bili zadovoljni. Njih se može razumeti. Počeli smo da gledamo u dokumentaciju. Ispostavilo se da postoji još nekoliko parametara koji mogu uticati na proces. Na primer, ako je executor u režimu čekanja — nakon koliko vremena možemo uzeti resurse od njega?
spark.dynamicAllocation.executorIdleTimeout=120sV našem případě — pokud vaše executory nic nedělají během dvou minut, prosím, vraťte je do společného poolu. Ale ani tento parametr často nestačil. Bylo vidět, že člověk již dlouho nic nedělá, ale zdroje se neuvolňují. Ukázalo se, že existuje ještě jeden speciální parametr — po uplynutí určitého času vybrat executory, které obsahují kešované údaje. Ve výchozím nastavení byl tento parametr nastaven na — nekonečno! Opraveno.
spark.dynamicAllocation.cachedExecutorIdleTimeout=600sTo znamená, že pokud veškeré vaše executory nic nedělají během 5 minut, vraťte je do společného poolu. V tomto režimu se rychlost uvolňování a přidělování zdrojů pro velké množství uživatelů stala přijatelnou. Počet nespokojených se snížil. Ale rozhodli jsme se jít dále a omezit maximální počet executorů pro jednu aplikaci — v podstatě pro jednoho účastníka programu.
spark.dynamicAllocation.maxExecutors=19Teď samozřejmě vznikli nespokojení z druhé strany — "klastr stojí, a já mám jen 19 executorů”, ale co se dá dělat — potřebujeme nějakou správnou rovnováhu. Není možné, aby byli všichni šťastní.
A ještě jeden malý příběh týkající se specifik naší situace. Někdo na praktickou hodinu přišel pozdě, a jejich Spark z nějakého důvodu nenastal. Podívali jsme se na počet volných zdrojů — zdálo se, že jsou. Spark by měl začít. Naštěstí k tomu momentu byla dokumentace již někde uložena v paměti, a vzpomněli jsme si, že při spuštění Spark hledá port, na kterém by měl začít. Pokud je první port v rozsahu obsazen, přejde na další v pořadí. Pokud je volný, zabere ho. A existuje parametr, který udává maximální počet pokusů pro toto. Ve výchozím nastavení — je to 16. Číslo méně než počet lidí v naší skupině na hodině. Tedy po 16 pokusech Spark to vzdal a řekl, že nemohu začít. Opraveno.
spark.port.maxRetries=50Teď povím o některých nastaveních, která už nejsou příliš spjata se specifikem naší situace.
Pro rychlejší start Spark se doporučuje zarchivovat složku jars, ležící v domovské direktori SPARK_HOME, a umístit ji na HDFS. Tímto způsobem nebude ztrácet čas načítáním těchto jarů na workery.
spark.yarn.archive=hdfs:///tmp/spark-archive.zipPrav tako, za hitrejše delovanje je priporočljivo uporabiti Kryo kot serijalizator. Je bolj optimiziran kot tisti, ki je privzet.
spark.serializer=org.apache.spark.serializer.KryoSerializerIn še eno dolgo prisotno težavo v Sparku, da pogosto odpade zaradi pomanjkanja pomnilnika. To se pogosto zgodi, ko delavci vse izračunajo in pošljejo rezultat na gonilnik. Ta parameter smo povečali. Privzeto je 1 GB, mi smo ga nastavili na 3.
spark.driver.maxResultSize=3072In zadnje, kot sladica. Kako nadgraditi Spark na različico 2.1 na HortonWorks distribuciji - HDP 2.5.3.0. Ta različica HDP vsebuje prednameščeno različico 2.0, vendar smo enkrat ugotovili, da se Spark precej aktivno razvija, in vsaka nova različica odpravlja nekatere napake ter ponuja dodatne možnosti, tudi za Python API, zato smo se odločili, da nadgradimo.
Prenesli smo različico z uradne spletne strani za Hadoop 2.7. Razširili smo jo in jo dali v mapo s HDP. Naredili smo simlinks, kot je treba. Začnemo — ne zažene se. Pojavi se zelo nenavadna napaka.
java.lang.NoClassDefFoundError: com/sun/jersey/api/client/config/ClientConfigPo iskanju na Googlu smo ugotovili, da Spark ni želel čakati, da Hadoop izda novo različico, in so se odločili uporabiti novo različico Jersey. Tam se sami med seboj prepirajo o tej temi na JIRI. Rešitev je bila — prenesti . To smo dali v mapo jars v SPARK_HOME, znova naredili zip in jo dali na HDFS.
To napako smo obšli, vendar se je pojavila nova in precej obširna.
org.apache.spark.SparkException: Yarn application has already ended! It might have been killed or unable to launch application masterPri tem smo poskusili zagnati različico 2.0 — vse je v redu. Poskusi ugotoviti, v čem je težava. Poglejali smo dnevnik te aplikacije in videli nekaj takega:
/usr/hdp/${hdp.version}/hadoop/lib/hadoop-lzo-0.6.0.${hdp.version}.jarNa splošno, iz kakršnega koli razloga, hdp.version se ni razrešil. Po iskanju smo našli rešitev. V Ambari je treba iti v nastavitve YARN in dodatno dodati parameter v custom yarn-site:
hdp.version=2.5.3.0-37Ta manažma je pomagala, in Spark je poletel. Preizkusili smo nekaj naših Jupyter zvezkov. Vse deluje. Na prvo lekcijo o Sparku v soboto (že jutri) smo pripravljeni!
UPD. Na lekciji se je pojavila še ena težava. V nekem trenutku YARN ni več izdal vsebnikov za Spark. V YARN je bilo treba popraviti parameter, ki je bil privzeto nastavljen na 0.2:
yarn.scheduler.capacity.maximum-am-resource-percent=0.8 To je pomeni, da je le 20 % virov sodelovalo pri dodeljevanju virov. Spremenili smo nastavitve in ponovno zagnali YARN. Težava je bila rešena, ostali udeleženci so prav tako lahko zagnali spark kontekst.
Izvor: habr.com
