Поглиблене занурення у внутрішні об’єкти Spark та архітектуру

Apache Spark - це розподілена загальна система кластерних обчислень із відкритим кодом. Додаток spark - це процес JVM, який запускає код користувача, використовуючи іскру як сторонній бібліотеці.

Як частина цього блогу, я покажу, як Spark працює над архітектурою пряжі, на прикладі та різних базових фонових процесах, які беруть участь, наприклад:

  • Іскровий контекст
  • Менеджер ресурсів пряжі, майстер додатків та запуск виконавців (контейнерів).
  • Налаштування змінних середовища, робочих ресурсів.
  • CoarseGrainedExecutorBackend і RPC на основі Netty.
  • Слухачі Spark.
  • Виконання роботи (логічний план, фізичний план).
  • Spark-WebUI.

Іскровий контекст

Контекст Spark - це перший рівень точки входу та серце будь-якого додатку іскри. Spark-shell - це не що інше, як REPL на основі Scala з іскровими двійковими файлами, який створить об'єкт sc, який називається spark context.

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

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 виконується на вузлі шлюзу, що є нічим іншим, як іскровою оболонкою. Це створить іскровий контекст і запустить програму.

До об'єкта контексту spark можна отримати доступ за допомогою sc.

Після створення контексту Spark він чекає ресурсів. Коли ресурси доступні, контекст Spark встановлює внутрішні служби та встановлює зв’язок із середовищем виконання Spark.

Менеджер ресурсів пряжі, майстер додатків та запуск виконавців (контейнерів).

Після створення контексту Spark він перевірятиметься з менеджером кластерів і запускатиме Application Master, тобто запускатиме контейнер та реєструватиме обробники сигналів .

Після запуску майстра додатків він встановлює зв’язок з драйвером.

Далі ApplicationMasterEndPoint запускає проксі-програму для підключення до менеджера ресурсів.

Тепер контейнер для пряжі виконуватиме наведені нижче операції, як показано на схемі.

ii) YarnRMClient зареєструється у майстра програми.

iii) YarnAllocator: запитає 3 контейнери-виконавці, кожен з 2 ядрами та 884 МБ пам'яті, включаючи 384 МБ службових витрат

iv) AM запускає Reporter Thread

Тепер Yarn Allocator отримує маркери від Driver для запуску вузлів Executor та запуску контейнерів.

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

Щоразу, коли контейнер запускається, він виконує наступні 3 дії в кожному з них.

  • Налаштування змінних env

Навколишнє середовище Spark (SparkEnv) - це середовище виконання із послугами Spark, які використовуються для взаємодії між собою для створення розподіленої обчислювальної платформи для додатка Spark.

  • Налаштування робочих ресурсів
  • Запуск контейнера

Контекст запуску виконавця YARN присвоює кожному виконавцю ідентифікатор виконавця для ідентифікації відповідного виконавця (через Spark WebUI) та запускає CoarseGrainedExecutorBackend.

CoarseGrainedExecutorBackend і RPC на основі Netty.

Отримавши ресурси у Менеджера ресурсів, ми побачимо, як виконавець запускається

CoarseGrainedExecutorBackend - це ExecutorBackend, який контролює життєвий цикл одного виконавця. Воно відправляє статус виконавця.

Коли запускається ExecutorRunnable, CoarseGrainedExecutorBackend реєструє кінцеву точку Executor RPC та обробники сигналів для зв'язку з драйвером (тобто з кінцевою точкою RPC CoarseGrainedScheduler) та повідомляє, що він готовий до запуску завдань.

RPC на основі мереж - використовується для зв'язку між робочими вузлами, контекстом іскри, виконавцями.

NettyRPCEndPoint використовується для відстеження стану результату робочого вузла.

RpcEndpointAddress - це логічна адреса кінцевої точки, зареєстрованої в середовищі RPC, з RpcAddress та іменем.

Це у форматі, як показано нижче:

Це перший момент, коли CoarseGrainedExecutorBackend ініціює зв'язок з драйвером, доступним на driverUrl через RpcEnv.

Слухачі Spark

SparkListener (прослуховувач планувальника) - це клас, який прослуховує події виконання з Spark's DAGScheduler і реєструє всю інформацію про події програми, таку як виконавець, деталі розподілу драйверів, а також завдання, етапи та завдання та інші зміни властивостей середовища.

SparkContext запускає LiveListenerBus, який знаходиться всередині драйвера. Він реєструє JobProgressListener з LiveListenerBus, який збирає всі дані для відображення статистики в інтерфейсі spark.

За замовчуванням буде включений лише прослуховувач для WebUI, але якщо ми хочемо додати інших слухачів, тоді ми можемо використовувати spark.extraListeners.

Spark поставляється з двома слухачами, які демонструють більшість заходів

i) StatsReportListener

ii) EventLoggingListener

EventLoggingListener:Якщо ви хочете додатково проаналізувати ефективність своїх програм, окрім того, що доступне як частина сервера історії Spark, тоді ви можете обробити дані журналу подій. Журнал подій Spark записує інформацію про оброблені завдання / етапи / завдання. Його можна ввімкнути, як показано нижче ...

Файл журналу подій можна прочитати, як показано нижче

  • Драйвер 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 можна створити двома способами.

i) Паралелізація існуючої колекції у вашій програмі драйверів

ii) Посилання на набір даних у зовнішній системі зберігання

RDD створюються або за допомогою файлу у файловій системі Hadoop, або існуючої колекції Scala у програмі драйвера, та її трансформації.

Візьмемо зразок фрагмента, як показано нижче

Виконання вищезазначеного фрагмента відбувається у 2 етапи.

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

Трансформації можна розділити на 2 типи

  • Вузьке перетворення: конвеєр операцій, який може виконуватися як один етап і не вимагає перемішування даних по розділах - наприклад, карта, фільтр тощо.

Тепер дані будуть зчитуватися в драйвері за допомогою широкомовної змінної.

  • Широке перетворення: Тут кожна операція вимагає перемішування даних, відтепер для кожного широкого перетворення буде створюватися новий етап - наприклад, reduceByKey тощо.

Ми можемо переглянути графік лінійного походження за допомогою toDebugString

6.2 Фізичний план:На цьому етапі, як тільки ми запускаємо дію на RDD, Планувальник DAG розглядає лінію RDD і придумує найкращий план виконання зі стадіями та завданнями разом із TaskSchedulerImpl і виконує завдання паралельно до набору завдань.

Після того, як ми виконаємо операцію дії, SparkContext запускає завдання та реєструє RDD до першого етапу (тобто до будь-яких широких перетворень) як частина DAGScheduler.

Тепер перед тим, як перейти до наступного етапу (Широкі перетворення), він перевірить, чи є дані розділу, які слід перетасувати, і чи відсутні якісь результати батьківської операції, від яких це залежить, якщо такий етап відсутній, то він повторно виконує цю частину операції, використовуючи DAG (Directed Acyclic Graph), що робить її стійкою до несправностей.

У разі відсутності завдань він призначає завдання виконавцям.

Кожне завдання призначається CoarseGrainedExecutorBackend виконавця.

Він отримує інформацію про блок із Namenode.

тепер він виконує обчислення і повертає результат.

Далі DAGScheduler шукає нещодавно запущені етапи та запускає наступну стадію (reduceByKey).

ShuffleBlockFetcherIterator забезпечує перемішування блоків.

Тепер операція зменшення ділиться на 2 завдання і виконується.

По завершенню кожного завдання виконавець повертає результат назад водієві.

Після завершення завдання відображається результат.

Spark-WebUI

Spark-UI допомагає зрозуміти процес виконання коду та час, необхідний для виконання певної роботи. Візуалізація допомагає виявити будь-які основні проблеми, що мають місце під час виконання, та додатково оптимізувати додаток іскри.

Ми побачимо візуалізацію Spark-UI як частину попереднього кроку 6.

Після завершення завдання ви зможете побачити такі деталі, як кількість етапів, кількість завдань, запланованих під час виконання завдання.

Клацнувши на виконані завдання, ми можемо переглянути візуалізацію DAG, тобто різні широкі та вузькі перетворення як її частину.

Ви можете бачити час виконання кожного етапу.

Після натискання на конкретну стадію як частину роботи, вона відображатиме всі деталі щодо місця розташування блоків даних, розміру даних, використовуваного виконавця, використовуваної пам’яті та часу, необхідного для виконання конкретного завдання. Він також показує кількість перетасовки, що відбуваються.

Далі ми можемо натиснути на вкладку Виконавці, щоб переглянути виконавця та використаний драйвер.

Тепер, коли ми побачили, як Spark працює внутрішньо, ви можете визначити потік виконання, використовуючи інтерфейс Spark, журнали та налаштовуючи Spark EventListeners, щоб визначити оптимальне рішення щодо подання завдання Spark.

Примітка : Команди, які були виконані, пов’язані з цим повідомленням, додаються як частина мого облікового запису GIT.

Подібним чином ви також можете прочитати більше тут:

  • Архітектура Sqoop в глибині з кодом.
  • Архітектура HDFS в глибині з кодом .
  • Архітектура вуликів у глибині з кодом .

Якщо ви теж хочете, ви можете зв’язатися зі мною в LinkedIn - Джайвардханом Редді.

Якщо вам сподобалось читати його, ви можете натиснути на плескання та повідомити про це інших. Якщо ви хочете, щоб я додав ще щось, будь ласка, залиште відповідь?