Задълбочете се във вътрешността на Spark и архитектурата

Apache Spark е разпределена рамка за клъстерни изчисления с общо предназначение с отворен код. Искровото приложение е JVM процес, който изпълнява потребителски код, използвайки искрата като библиотека на трета страна.

Като част от този блог ще покажа начина, по който Spark работи върху архитектурата на преждата, с пример и различните базови фонови процеси, които участват, като например:

  • Искрен контекст
  • Мениджър на ресурси за прежди, капитан на приложения и стартиране на изпълнители (контейнери).
  • Настройване на променливи на средата, ресурси за работа.
  • CoarseGrainedExecutorBackend и базирани на Netty RPC.
  • SparkListeners.
  • Изпълнение на работа (логически план, физически план).
  • Spark-WebUI.

Искрен контекст

Spark context е първото ниво на влизане и сърцето на всяко приложение на искра. Spark-shell не е нищо друго освен базиран на Scala REPL с искрови двоични файлове, които ще създадат обект sc, наречен искра контекст.

Можем да стартираме искровата обвивка, както е показано по-долу:

spark-shell --master yarn \ --conf spark.ui.port=12345 \ --num-executors 3 \ --executor-cores 2 \ --executor-memory 500M

Като част от искровата обвивка споменахме броя на изпълнителите. Те посочват броя на работните възли, които трябва да се използват, и броя на ядрата за всеки от тези работни възли за паралелно изпълнение на задачи.

Или можете да стартирате искра черупка, като използвате конфигурацията по подразбиране.

spark-shell --master yarn

Конфигурациите присъстват като част от spark-env.sh

Нашата програма Driver се изпълнява на Gateway възел, който не е нищо друго освен искрова обвивка. Той ще създаде искров контекст и ще стартира приложение.

Контекстният обект на искра може да бъде достъпен с помощта на sc.

След създаването на контекста на Spark той изчаква ресурсите. След като ресурсите са налични, контекстът на Spark настройва вътрешни услуги и установява връзка с среда за изпълнение на Spark.

Мениджър на ресурси за прежди, капитан на приложения и стартиране на изпълнители (контейнери).

След като се създаде контекстът на Spark, той ще провери с мениджъра на клъстери и ще стартира Application Master, т.е. стартира контейнер и регистрира обработващите сигнали .

След като Application Master се стартира, той установява връзка с драйвера.

След това ApplicationMasterEndPoint задейства прокси приложение, за да се свърже с мениджъра на ресурси.

Сега контейнерът за прежди ще извърши следните операции, както е показано на диаграмата.

ii) YarnRMClient ще се регистрира при Master Master.

iii) YarnAllocator: Ще поиска 3 изпълнителни контейнера, всеки с 2 ядра и 884 MB памет, включително 384 MB режийни

iv) AM стартира Reporter Thread

Сега Yarn Allocator получава жетони от Driver за стартиране на възлите Executor и стартиране на контейнерите.

Настройване на променливи на средата, ресурси за работа и стартиране на контейнери.

Всеки път, когато се стартира контейнер, той прави следните 3 неща във всяко от тях.

  • Настройване на env променливи

Spark Runtime Environment (SparkEnv) е средата на изпълнение с услугите на Spark, които се използват за взаимодействие помежду си, за да се създаде разпределена изчислителна платформа за приложение Spark.

  • Създаване на ресурси за работа
  • Стартиращ контейнер

Контекстът за стартиране на изпълнител YARN присвоява на всеки изпълнител идентификатор на изпълнител, за да идентифицира съответния изпълнител (чрез Spark WebUI) и стартира CoarseGrainedExecutorBackend.

CoarseGrainedExecutorBackend и базирани на Netty RPC.

След получаване на ресурси от Resource Manager, ще видим изпълнителя да стартира

CoarseGrainedExecutorBackend е ExecutorBackend, който контролира жизнения цикъл на един изпълнител. Той изпраща статуса на изпълнителя на водача.

Когато ExecutorRunnable е стартиран, CoarseGrainedExecutorBackend регистрира Executor RPC крайната точка и обработчиците на сигнали, за да комуникират с драйвера (т.е. с CoarseGrainedScheduler RPC крайна точка) и да информират, че са готови да стартират задачи.

RPC, базиран на Netty - Използва се за комуникация между работни възли, искров контекст, изпълнители.

NettyRPCEndPoint се използва за проследяване на състоянието на резултата на работния възел.

RpcEndpointAddress е логическият адрес за крайна точка, регистрирана в RPC среда, с RpcAddress и име.

Той е във формата, както е показано по-долу:

Това е първият момент, когато CoarseGrainedExecutorBackend инициира комуникация с драйвера, наличен в driverUrl чрез RpcEnv.

SparkListeners

SparkListener (слушател на Scheduler) е клас, който слуша събития за изпълнение от DAGScheduler на Spark и регистрира цялата информация за събитията на приложение, като например изпълнителя, подробностите за разпределението на драйверите, заедно с задания, етапи и задачи и други промени в свойствата на средата.

SparkContext стартира LiveListenerBus, който се намира вътре в драйвера. Той регистрира JobProgressListener с LiveListenerBus, който събира всички данни, за да покаже статистиката в потребителския интерфейс на spark.

По подразбиране само слушателят за WebUI ще бъде активиран, но ако искаме да добавим други слушатели, тогава можем да използваме spark.extraListeners.

Spark идва с двама слушатели, които показват повечето от дейностите

i) StatsReportListener

ii) EventLoggingListener

EventLoggingListener:Ако искате да анализирате допълнително производителността на вашите приложения отвъд наличното като част от сървъра за история на Spark, тогава можете да обработите данните от дневника на събитията. Spark Event Log записва информация за обработени задачи / етапи / задачи. Може да се активира, както е показано по-долу ...

Регистрационният файл на събитията може да бъде прочетен, както е показано по-долу

  • Драйверът Spark влиза в метриките за натоварване / изпълнение на заданието в директорията spark.evenLog.dir като JSON файлове.
  • На всеки приложение има по един файл, имената на файловете съдържат идентификатора на приложението (следователно включващ клеймо за време) application_1540458187951_38909.

Той показва вида на събитията и броя на записите за всеки.

Сега, нека добавим StatsReportListener към spark.extraListenersи проверете състоянието на заданието.

Активирайте INFO ниво на регистриране за org.apache.spark.scheduler.StatsReportListener регистратор, за да видите събитията на Spark.

За да активирате слушателя, го регистрирайте в SparkContext. Може да се направи по два начина.

i) Използване на метод SparkContext.addSparkListener (слушател: SparkListener) във вашето приложение Spark.

Кликнете върху връзката, за да внедрите персонализирани слушатели - CustomListener

ii) Използване на опцията за команден ред conf

Нека прочетем примерен файл и да извършим операция за броене, за да видим StatsReportListener.

Изпълнение на работа (логически план, физически план).

В Spark RDD ( еластичен разпределен набор от данни ) е първото ниво на абстракционния слой. Това е колекция от елементи, разпределени между възлите на клъстера, които могат да бъдат експлоатирани паралелно. RDD могат да бъдат създадени по 2 начина.

i) Паралелизиране на съществуваща колекция във вашата програма за драйвери

ii) Препращане към набор от данни във външна система за съхранение

RDD се създават или чрез използване на файл във файловата система Hadoop, или на съществуваща колекция Scala в програмата за драйвери и трансформирането му.

Нека вземем примерен фрагмент, както е показано по-долу

Изпълнението на горния фрагмент се извършва на 2 фази.

6.1 Логически план: В тази фаза се създава RDD, като се използва набор от трансформации. Той проследява тези трансформации в програмата на драйвера чрез изграждане на изчислителна верига (серия от RDD) като графика на трансформациите, за да се получи един RDD, наречен Графика на родословието .

Трансформациите могат да бъдат разделени на 2 вида

  • Тясна трансформация: Конвейер от операции, които могат да бъдат изпълнени като един етап и не изискват данните да бъдат разбърквани в дяловете - например Карта, филтър и др.

Сега данните ще бъдат прочетени в драйвера с помощта на излъчваната променлива.

  • Широко преобразуване: Тук всяка операция изисква данните да се разбъркват, занапред за всяка широка трансформация ще се създаде нов етап - например, намаляванеByKey и т.н.

Можем да видим графика на родословието, като използваме toDebugString

6.2 Физически план:В тази фаза, след като задействаме действие върху RDD, DAG Scheduler разглежда родословната линия на RDD и изготвя най-добрия план за изпълнение със етапи и задачи заедно с TaskSchedulerImpl и паралелно изпълнява заданието в набор от задачи.

След като извършим операция за действие, SparkContext задейства задача и регистрира RDD до първия етап (т.е. преди всякакви широки трансформации) като част от DAGScheduler.

Сега, преди да преминете към следващия етап (Широки трансформации), той ще провери дали има данни за дялове, които трябва да бъдат разбъркани и дали има липсващи резултати от родителска операция, от които зависи, ако липсва такъв етап, той отново изпълнява тази част от операцията, като използва DAG (Directed Acyclic Graph), което я прави устойчива на повреди.

В случай на липсващи задачи той възлага задачи на изпълнители.

Всяка задача се присвоява на CoarseGrainedExecutorBackend на изпълнителя.

Той получава информацията за блока от Namenode.

сега той извършва изчислението и връща резултата.

След това DAGScheduler търси новоизпълнимите етапи и задейства следващия етап (намаляванеByKey) операция.

ShuffleBlockFetcherIterator получава блоковете да бъдат разбъркани.

Сега операцията за намаляване се разделя на 2 задачи и се изпълнява.

След приключване на всяка задача, изпълнителят връща резултата обратно на водача.

След като заданието приключи, резултатът се показва.

Spark-WebUI

Spark-UI помага за разбирането на потока на изпълнение на кода и времето, необходимо за завършване на определена работа. Визуализацията помага да се открият всички основни проблеми, които се случват по време на изпълнението, и да се оптимизира допълнително приложението на искра.

Ще видим визуализацията на Spark-UI като част от предишната стъпка 6.

След като заданието приключи, можете да видите подробности за заданието, като например броя на етапите, броя на задачите, планирани по време на изпълнението на заданието.

При щракване върху завършените задачи можем да видим визуализацията на DAG, т.е. различните широки и тесни трансформации като част от нея.

Можете да видите времето за изпълнение на всеки етап.

След като щракнете върху определен етап като част от заданието, той ще покаже пълните подробности за това къде се намират блоковете данни, размера на данните, използвания изпълнител, използваната памет и времето, необходимо за изпълнението на определена задача. Той също така показва броя на разбъркванията, които се извършват.

Освен това можем да кликнете върху раздела Изпълнители, за да видите използвания Изпълнител и драйвер.

Сега, когато видяхме как Spark работи вътрешно, можете да определите потока на изпълнение, като използвате Spark UI, регистрационни файлове и променяте Spark EventListeners, за да определите оптимално решение за подаване на Spark работа.

Забележка : Командите, които бяха изпълнени, свързани с тази публикация, се добавят като част от моя акаунт в GIT.

По същия начин можете да прочетете повече тук:

  • Sqoop архитектура в дълбочина с код.
  • HDFS архитектура в дълбочина с код .
  • Архитектура на кошера в дълбочина с код .

Ако и вие искате, можете да се свържете с мен в LinkedIn - Jayvardhan Reddy.

Ако ви е било приятно да го прочетете, можете да щракнете с ръкопляскане и да уведомите другите за това. Ако искате да добавя нещо друго, моля не се колебайте да оставите отговор?