Habr, hei! Eilen päällä
Pieni johdatus Sparkin käyttöön. Meillä on kolmen kuukauden ohjelma
Käyttömme erikoisuutena on, että Sparkilla samanaikaisesti työskentelevien henkilöiden määrä voi olla yhtä suuri kuin koko ryhmä. Esimerkiksi seminaarissa, kun kaikki yrittävät jotain yhtä aikaa ja toistavat opettajamme perässä. Ja tämä ei ole paljon - joskus jopa 40 henkilöä. Maailmassa ei todennäköisesti ole monia yrityksiä, jotka kohtaavat tällaisen käyttötapauksen.
Seuraavaksi kerron sinulle, kuinka ja miksi valitsimme tietyt konfigurointiparametrit.
Aloitetaan aivan alusta. Sparkilla on kolme vaihtoehtoa toimia klusterissa: itsenäinen, käyttämällä Mesosia ja käyttämällä YARNia. Päätimme valita kolmannen vaihtoehdon, koska se oli meille järkevää. Meillä on jo hadoop-klusteri. Osallistujamme tuntevat jo hyvin sen arkkitehtuurin. Käytetään LANKAA.
spark.master=yarn
Vielä mielenkiintoisempaa. Jokaisella näistä kolmesta käyttöönottovaihtoehdosta on kaksi käyttöönottovaihtoehtoa: asiakas ja klusteri. Perustuu
spark.deploy-mode=client
Yleensä tästä lähtien Spark toimii jotenkin LANKAlla, mutta tämä ei riittänyt meille. Koska meillä on ohjelma big datasta, välillä osallistujat eivät riittäneet tasaisen resurssien viipaloinnin puitteissa saadulle. Ja sitten löysimme mielenkiintoisen asian - dynaamisen resurssien allokoinnin. Lyhyesti sanottuna pointti on tämä: jos sinulla on vaikea tehtävä ja klusteri on vapaa (esimerkiksi aamulla), tämän vaihtoehdon käyttäminen Spark voi antaa sinulle lisäresursseja. Välttämättömyys lasketaan siellä ovelan kaavan mukaan. Emme mene yksityiskohtiin - se toimii hyvin.
spark.dynamicAllocation.enabled=true
Asetimme tämän parametrin, ja käynnistyksen yhteydessä Spark kaatui eikä käynnistynyt. Juuri niin, koska minun oli pakko lukea se
spark.shuffle.service.enabled=true
Miksi sitä tarvitaan? Kun työmme ei enää vaadi niin paljon resursseja, Sparkin pitäisi palauttaa ne yhteiseen pooliin. Melkein minkä tahansa MapReduce-tehtävän aikaa vievin vaihe on Shuffle-vaihe. Tämän parametrin avulla voit tallentaa tässä vaiheessa luodut tiedot ja vapauttaa suorittajat vastaavasti. Ja toimeenpanija on prosessi, joka laskee kaiken työntekijästä. Siinä on tietty määrä prosessoriytimiä ja tietty määrä muistia.
Tämä parametri on lisätty. Kaikki näytti toimivan. Tuli havaittavaksi, että osallistujille annettiin itse asiassa enemmän resursseja, kun he tarvitsivat niitä. Mutta toinen ongelma ilmaantui - jossain vaiheessa muut osallistujat heräsivät ja halusivat myös käyttää Sparkia, mutta siellä kaikki oli kiireistä ja he olivat tyytymättömiä. Niitä voidaan ymmärtää. Aloimme tarkastella asiakirjoja. Kävi ilmi, että on olemassa useita muita parametreja, joilla voidaan vaikuttaa prosessiin. Esimerkiksi jos toimeenpanija on valmiustilassa, minkä ajan kuluttua siitä voidaan ottaa resursseja?
spark.dynamicAllocation.executorIdleTimeout=120s
Meidän tapauksessamme, jos toimeenpanijasi eivät tee mitään kahteen minuuttiin, palauta heidät yhteiseen pooliin. Mutta tämä parametri ei aina riittänyt. Oli selvää, että henkilö ei ollut tehnyt mitään pitkään aikaan, eikä resursseja vapautunut. Kävi ilmi, että on myös erityinen parametri - minkä ajan kuluttua valita välimuistiin tallennettuja tietoja sisältävät suorittajat. Oletuksena tämä parametri oli ääretön! Korjasimme sen.
spark.dynamicAllocation.cachedExecutorIdleTimeout=600s
Eli jos toimeenpanijasi eivät tee mitään 5 minuuttiin, anna heidät yhteiseen pooliin. Tässä tilassa resurssien vapauttamisen ja myöntämisen nopeus suurelle määrälle käyttäjiä on tullut kunnolliseksi. Tyytymättömyyden määrä on vähentynyt. Mutta päätimme mennä pidemmälle ja rajoittaa suorittajien enimmäismäärää hakemusta kohti - olennaisesti ohjelman osallistujaa kohti.
spark.dynamicAllocation.maxExecutors=19
Nyt tietysti on tyytymättömiä toisella puolella - "klusteri on tyhjäkäynnillä, ja minulla on vain 19 toimeenpanijaa", mutta mitä voit tehdä? Tarvitsemme jonkinlaisen oikean tasapainon. Kaikkia ei voi tehdä onnelliseksi.
Ja vielä yksi pieni tarina, joka liittyy tapauksemme yksityiskohtiin. Jotenkin monet ihmiset olivat myöhässä käytännön tunnilta, eikä Spark jostain syystä lähtenyt heidän puolestaan käyntiin. Tarkastelimme vapaiden resurssien määrää - se näyttää olevan siellä. Kipinän pitäisi käynnistyä. Onneksi siihen mennessä dokumentaatio oli jo lisätty alakuoreen jonnekin ja muistimme, että Spark etsii käynnistyessään porttia, josta aloittaa. Jos alueen ensimmäinen portti on varattu, se siirtyy järjestyksessä seuraavaan. Jos se on ilmainen, se kaappaa. Ja siellä on parametri, joka osoittaa yritysten enimmäismäärän tätä varten. Oletusarvo on 16. Määrä on pienempi kuin ryhmämme henkilömäärä luokassa. Näin ollen 16 yrityksen jälkeen Spark luovutti ja sanoi, että en voinut aloittaa. Olemme korjanneet tämän asetuksen.
spark.port.maxRetries=50
Seuraavaksi kerron joistakin asetuksista, jotka eivät liity kovinkaan tapauksemme erityispiirteisiin.
Sparkin käynnistämiseksi nopeammin on suositeltavaa arkistoida SPARK_HOME-kotihakemistossa oleva jars-kansio ja laittaa se HDFS:ään. Silloin hän ei tuhlaa aikaa näiden jarnikien lataamiseen työntekijöiden toimesta.
spark.yarn.archive=hdfs:///tmp/spark-archive.zip
On myös suositeltavaa käyttää kryoa serialisoijana toiminnan nopeuttamiseksi. Se on optimoitumpi kuin oletus.
spark.serializer=org.apache.spark.serializer.KryoSerializer
Ja Sparkissa on myös pitkäaikainen ongelma, että se usein kaatuu muistista. Usein tämä tapahtuu sillä hetkellä, kun työntekijät ovat laskeneet kaiken ja lähettäneet tuloksen kuljettajalle. Teimme tätä parametria suuremmaksi itsellemme. Oletuksena se on 1 Gt, teimme siitä 3.
spark.driver.maxResultSize=3072
Ja lopuksi jälkiruokana. Kuinka päivittää Spark versioon 2.1 HortonWorks-jakelussa - HDP 2.5.3.0. Tämä HDP-versio sisältää esiasennetun version 2.0, mutta päätimme kerran itse, että Spark kehittyy melko aktiivisesti, ja jokainen uusi versio korjaa joitain bugeja sekä tarjoaa lisäominaisuuksia, mukaan lukien python API:lle, joten päätimme, mitä tarvitsee tehty on päivitys.
Ladattu versio Hadoop 2.7:n viralliselta verkkosivustolta. Pura se ja laita se HDP-kansioon. Asensimme symlinkit tarpeen mukaan. Käynnistämme sen - se ei käynnisty. Kirjoittaa erittäin outo virhe.
java.lang.NoClassDefFoundError: com/sun/jersey/api/client/config/ClientConfig
Googlaamisen jälkeen saimme selville, että Spark päätti olla odottamatta Hadoopin syntymää ja päätti käyttää pelipaidan uutta versiota. He itse väittelevät keskenään tästä aiheesta JIRAssa. Ratkaisu oli ladata
Kiertimme tämän virheen, mutta syntyi uusi ja melko virtaviivaistettu virhe.
org.apache.spark.SparkException: Yarn application has already ended! It might have been killed or unable to launch application master
Samaan aikaan yritämme ajaa versiota 2.0 - kaikki on ok. Yritä arvata, mitä tapahtuu. Tutkimme tämän sovelluksen lokeja ja näimme jotain tällaista:
/usr/hdp/${hdp.version}/hadoop/lib/hadoop-lzo-0.6.0.${hdp.version}.jar
Yleensä jostain syystä hdp.versio ei ratkennut. Googlaamisen jälkeen löysimme ratkaisun. Sinun täytyy mennä Ambarin LANKA-asetuksiin ja lisätä sinne parametri mukautettuun lankasivustoon:
hdp.version=2.5.3.0-37
Tämä taika auttoi, ja Spark lähti liikkeelle. Testasimme useita jupyter-kannettaviamme. Kaikki toimii. Olemme valmiita ensimmäiseen Spark-tuntiin lauantaina (huomenna)!
UPD. Oppitunnin aikana paljastui toinen ongelma. YARN lopetti jossain vaiheessa säiliöiden tarjoamisen Sparkille. YARNissa oli tarpeen korjata parametri, joka oletuksena oli 0.2:
yarn.scheduler.capacity.maximum-am-resource-percent=0.8
Eli vain 20 % resursseista osallistui resurssien jakamiseen. Parametrien muuttamisen jälkeen ladattiin LANKA uudelleen. Ongelma ratkesi ja myös muut osallistujat pystyivät ajamaan kipinäkontekstia.
Lähde: will.com