Habr, hei! I går på
En liten introduksjon til hvordan vi bruker Spark. Vi har et tre måneders program
Det særegne ved bruken vår er at antall personer som samtidig jobber med Spark kan være lik hele gruppen. For eksempel på et seminar, når alle prøver noe samtidig og gjentar etter læreren vår. Og dette er ikke mye - noen ganger opptil 40 personer. Det er nok ikke mange selskaper i verden som står overfor en slik brukssak.
Deretter vil jeg fortelle deg hvordan og hvorfor vi valgte visse konfigurasjonsparametere.
La oss starte helt fra begynnelsen. Spark har 3 alternativer for å kjøre på en klynge: frittstående, ved hjelp av Mesos og bruk av GARN. Vi bestemte oss for å velge det tredje alternativet fordi det ga mening for oss. Vi har allerede en hadoop-klynge. Våre deltakere er allerede godt kjent med arkitekturen. La oss bruke GARN.
spark.master=yarn
Mer interessant. Hvert av disse tre distribusjonsalternativene har to distribusjonsalternativer: klient og klynge. Basert
spark.deploy-mode=client
Generelt vil Spark fra nå av på en eller annen måte fungere på YARN, men dette var ikke nok for oss. Siden programmet vårt handler om big data, hadde deltakerne noen ganger ikke nok av det som ble oppnådd innenfor rammen av en jevn oppskjæring av ressurser. Og så fant vi en interessant ting - dynamisk ressursallokering. Kort sagt, poenget er dette: hvis du har en vanskelig oppgave og klyngen er ledig (for eksempel om morgenen), kan det å bruke dette alternativet Spark gi deg ekstra ressurser. Nødvendigheten beregnes der etter en utspekulert formel. Vi vil ikke gå inn på detaljer - det fungerer bra.
spark.dynamicAllocation.enabled=true
Vi satte denne parameteren, og ved oppstart krasjet Spark og startet ikke. Det stemmer, for jeg måtte lese den
spark.shuffle.service.enabled=true
Hvorfor trengs det? Når jobben vår ikke lenger krever så mye ressurser, bør Spark returnere dem til felles basseng. Det mest tidkrevende stadiet i nesten alle MapReduce-oppgaver er Shuffle-stadiet. Denne parameteren lar deg lagre dataene som er generert på dette stadiet og frigi utførerne tilsvarende. Og utførende er prosessen som beregner alt på arbeideren. Den har et visst antall prosessorkjerner og en viss mengde minne.
Denne parameteren er lagt til. Alt så ut til å fungere. Det ble merkbart at deltakerne faktisk fikk mer ressurser når de trengte dem. Men et annet problem oppsto - på et tidspunkt våknet andre deltakere og ville også bruke Spark, men alt var travelt der, og de var misfornøyde. De kan forstås. Vi begynte å se på dokumentasjonen. Det viste seg at det er en rekke andre parametere som kan brukes for å påvirke prosessen. For eksempel, hvis utføreren er i standby-modus, etter hvilken tid kan ressurser tas fra den?
spark.dynamicAllocation.executorIdleTimeout=120s
I vårt tilfelle, hvis eksekutorene ikke gjør noe i løpet av to minutter, vennligst returner dem til fellesbassenget. Men denne parameteren var ikke alltid nok. Det var tydelig at personen ikke hadde gjort noe på lenge, og ressurser ble ikke frigjort. Det viste seg at det også er en spesiell parameter - etter hvilken tid for å velge eksekutører som inneholder hurtigbufrede data. Som standard var denne parameteren uendelig! Vi rettet det.
spark.dynamicAllocation.cachedExecutorIdleTimeout=600s
Det vil si at hvis eksekutorene ikke gjør noe på 5 minutter, gi dem til felles basseng. I denne modusen har hastigheten på å frigjøre og utstede ressurser for et stort antall brukere blitt anstendig. Mengden misnøye har gått ned. Men vi bestemte oss for å gå lenger og begrense det maksimale antallet eksekutører per søknad - i hovedsak per programdeltaker.
spark.dynamicAllocation.maxExecutors=19
Nå er det selvfølgelig misfornøyde mennesker på den andre siden - "klyngen er inaktiv, og jeg har bare 19 eksekutorer," men hva kan du gjøre? Vi trenger en slags riktig balanse. Du kan ikke gjøre alle glade.
Og enda en liten historie knyttet til detaljene i saken vår. På en eller annen måte kom flere personer for sent til en praktisk leksjon, og av en eller annen grunn startet ikke Spark for dem. Vi så på mengden ledige ressurser – det ser ut til å være der. Gnisten skal starte. Heldigvis var dokumentasjonen allerede på det tidspunktet lagt til underbarken et sted, og vi husket at når Spark ble lansert, leter etter en port å starte på. Hvis den første porten i området er opptatt, flyttes den til den neste i rekkefølge. Hvis det er gratis, fanger det opp. Og det er en parameter som indikerer maksimalt antall forsøk for dette. Standard er 16. Antallet er mindre enn antall personer i gruppen vår i klassen. Følgelig, etter 16 forsøk, ga Spark opp og sa at jeg ikke kunne starte. Vi har korrigert denne innstillingen.
spark.port.maxRetries=50
Deretter skal jeg fortelle deg om noen innstillinger som ikke er veldig relatert til detaljene i saken vår.
For å starte Spark raskere, anbefales det å arkivere jars-mappen som ligger i SPARK_HOME-hjemmekatalogen og legge den på HDFS. Da vil han ikke kaste bort tid på å laste disse jarnikene av arbeidere.
spark.yarn.archive=hdfs:///tmp/spark-archive.zip
Det anbefales også å bruke kryo som en serializer for raskere drift. Den er mer optimalisert enn standarden.
spark.serializer=org.apache.spark.serializer.KryoSerializer
Og det er også et langvarig problem med Spark at den ofte krasjer fra minnet. Ofte skjer dette i det øyeblikket arbeiderne har beregnet alt og sender resultatet til sjåføren. Vi gjorde denne parameteren større for oss selv. Som standard er det 1 GB, vi gjorde det til 3.
spark.driver.maxResultSize=3072
Og til slutt, som dessert. Slik oppdaterer du Spark til versjon 2.1 på HortonWorks-distribusjon - HDP 2.5.3.0. Denne versjonen av HDP inneholder en forhåndsinstallert versjon 2.0, men vi bestemte oss en gang for oss selv at Spark utvikler seg ganske aktivt, og hver nye versjon fikser noen feil og gir tilleggsfunksjoner, inkludert for python API, så vi bestemte oss for hva som må til gjøres er en oppdatering.
Lastet ned versjonen fra den offisielle nettsiden for Hadoop 2.7. Pakket den ut og satte den i HDP-mappen. Vi installerte symbolkoblingene etter behov. Vi lanserer den - den starter ikke. Skriver en veldig uklar feil.
java.lang.NoClassDefFoundError: com/sun/jersey/api/client/config/ClientConfig
Etter å ha googlet fant vi ut at Spark bestemte seg for ikke å vente til Hadoop ble født, og bestemte oss for å bruke den nye versjonen av jersey. Selv krangler de med hverandre om dette temaet i JIRA. Løsningen var å laste ned
Vi kom rundt denne feilen, men en ny og ganske strømlinjeformet en oppsto.
org.apache.spark.SparkException: Yarn application has already ended! It might have been killed or unable to launch application master
Samtidig prøver vi å kjøre versjon 2.0 - alt er ok. Prøv å gjette hva som skjer. Vi så på loggene til denne applikasjonen og så noe sånt som dette:
/usr/hdp/${hdp.version}/hadoop/lib/hadoop-lzo-0.6.0.${hdp.version}.jar
Generelt løste ikke hdp.version seg av en eller annen grunn. Etter å ha googlet, fant vi en løsning. Du må gå til GARN-innstillingene i Ambari og legge til en parameter der til egendefinert garnside:
hdp.version=2.5.3.0-37
Denne magien hjalp, og Spark tok av. Vi testet flere av våre Jupyter bærbare datamaskiner. Alt fungerer. Vi er klare for første Spark-time på lørdag (i morgen)!
UPD. I løpet av timen dukket det opp et annet problem. På et tidspunkt sluttet YARN å levere containere til Spark. I YARN var det nødvendig å korrigere parameteren, som som standard var 0.2:
yarn.scheduler.capacity.maximum-am-resource-percent=0.8
Det vil si at kun 20 % av ressursene deltok i ressursfordelingen. Etter å ha endret parameterne, lastet vi inn GARN på nytt. Problemet ble løst og resten av deltakerne kunne også kjøre gnistkontekst.
Kilde: www.habr.com