تكوين شرارة على الغزل

حبر، مرحبا! يوم أمس لقاء مخصص لـ Apache Spark، من الرجال من شركة Rambler&Co، كان هناك الكثير من الأسئلة من المشاركين المتعلقة بتكوين هذه الأداة. قررنا أن نسير على خطاه ونشارك تجربتنا. الموضوع ليس سهلاً - لذلك ندعوك لمشاركة تجربتك في التعليقات، ربما نفهم أيضًا ونستخدم شيئًا خاطئًا.

مقدمة بسيطة عن كيفية استخدامنا لـSpark. لدينا برنامج لمدة ثلاثة أشهر "أخصائي البيانات الضخمة"وطوال الوحدة الثانية، يعمل المشاركون على هذه الأداة. وعليه فإن مهمتنا كمنظمين هي إعداد المجموعة للاستخدام في مثل هذه الحالة.

خصوصية استخدامنا هي أن عدد الأشخاص الذين يعملون في وقت واحد على Spark يمكن أن يكون مساوياً للمجموعة بأكملها. على سبيل المثال، في ندوة، عندما يحاول الجميع شيئًا ما في نفس الوقت ويكررونه بعد معلمنا. وهذا ليس كثيرًا - أحيانًا يصل إلى 40 شخصًا. ربما لا توجد العديد من الشركات في العالم التي تواجه حالة الاستخدام هذه.

بعد ذلك، سأخبرك كيف ولماذا اخترنا معلمات تكوين معينة.

لنبدأ من البداية. لدى Spark 3 خيارات للتشغيل على مجموعة: مستقلة، باستخدام Mesos، وباستخدام YARN. قررنا أن نختار الخيار الثالث لأنه منطقي بالنسبة لنا. لدينا بالفعل مجموعة hadoop. المشاركون لدينا على دراية جيدة بهندسته المعمارية. دعونا نستخدم الغزل.

spark.master=yarn

علاوة على ذلك أكثر إثارة للاهتمام. يحتوي كل خيار من خيارات النشر الثلاثة هذه على خيارين للنشر: العميل والمجموعة. قائم على توثيق والروابط المختلفة على الإنترنت، يمكننا أن نستنتج أن العميل مناسب للعمل التفاعلي - على سبيل المثال، من خلال دفتر Jupyter، والكتلة أكثر ملاءمة لحلول الإنتاج. في حالتنا، كنا مهتمين بالعمل التفاعلي، لذلك:

spark.deploy-mode=client

بشكل عام، من الآن فصاعدا، ستعمل Spark بطريقة أو بأخرى على الغزل، لكن هذا لم يكن كافيا بالنسبة لنا. نظرًا لأن لدينا برنامجًا يتعلق بالبيانات الضخمة، ففي بعض الأحيان لم يكن لدى المشاركين ما يكفي مما تم الحصول عليه في إطار التقسيم المتساوي للموارد. ثم وجدنا شيئًا مثيرًا للاهتمام - التخصيص الديناميكي للموارد. باختصار، النقطة هي كما يلي: إذا كان لديك مهمة صعبة والمجموعة مجانية (على سبيل المثال، في الصباح)، فإن استخدام هذا الخيار Spark يمكن أن يوفر لك موارد إضافية. فالضرورة تُحسب هناك وفق معادلة ماكرة. لن نخوض في التفاصيل، فهو يعمل بشكل جيد.

spark.dynamicAllocation.enabled=true

قمنا بتعيين هذه المعلمة، وعند بدء التشغيل، تعطلت Spark ولم تبدأ. هذا صحيح، لأنه كان علي أن أقرأه الوثائق بحرص أكبر. تنص على أنه لكي يكون كل شيء على ما يرام، تحتاج أيضًا إلى تمكين معلمة إضافية.

spark.shuffle.service.enabled=true

لماذا هو مطلوب؟ عندما لا تتطلب مهمتنا الكثير من الموارد، يجب على Spark إعادتها إلى المجموعة المشتركة. المرحلة الأكثر استهلاكًا للوقت في أي مهمة MapReduce تقريبًا هي مرحلة Shuffle. تسمح لك هذه المعلمة بحفظ البيانات التي تم إنشاؤها في هذه المرحلة وتحرير المنفذين وفقًا لذلك. والمنفذ هو العملية التي تحسب كل شيء على العامل. يحتوي على عدد معين من نوى المعالج وكمية معينة من الذاكرة.

تمت إضافة هذه المعلمة. يبدو أن كل شيء يعمل. أصبح من الملاحظ أن المشاركين حصلوا بالفعل على المزيد من الموارد عندما احتاجوا إليها. ولكن نشأت مشكلة أخرى - في مرحلة ما، استيقظ المشاركون الآخرون وأرادوا أيضًا استخدام Spark، لكن كل شيء كان مشغولاً هناك، وكانوا غير سعداء. يمكن فهمهم. بدأنا في النظر في الوثائق. اتضح أن هناك عددًا من المعلمات الأخرى التي يمكن استخدامها للتأثير على العملية. على سبيل المثال، إذا كان المنفذ في وضع الاستعداد، فبعد أي وقت يمكن أخذ الموارد منه؟

spark.dynamicAllocation.executorIdleTimeout=120s

في حالتنا، إذا لم يفعل منفذوك أي شيء لمدة دقيقتين، فيرجى إعادتهم إلى المجمع المشترك. لكن هذه المعلمة لم تكن كافية دائمًا. كان من الواضح أن الشخص لم يفعل أي شيء لفترة طويلة، ولم يتم تحرير الموارد. اتضح أن هناك أيضًا معلمة خاصة - بعد أي وقت يتم تحديد المنفذين الذين يحتويون على بيانات مخزنة مؤقتًا. بشكل افتراضي، كانت هذه المعلمة اللانهاية! قمنا بتصحيحه.

spark.dynamicAllocation.cachedExecutorIdleTimeout=600s

وهذا يعني أنه إذا لم يفعل منفذوك أي شيء لمدة 5 دقائق، فامنحهم للمجمع المشترك. في هذا الوضع، أصبحت سرعة إطلاق وإصدار الموارد لعدد كبير من المستخدمين لائقة. لقد انخفضت كمية السخط. لكننا قررنا المضي قدمًا وتحديد الحد الأقصى لعدد المنفذين لكل تطبيق - لكل مشارك في البرنامج بشكل أساسي.

spark.dynamicAllocation.maxExecutors=19

والآن، بطبيعة الحال، هناك أشخاص غير راضين على الجانب الآخر ــ "المجموعة خاملة، وليس لدي سوى 19 منفذاً"، ولكن ماذا بوسعنا أن نفعل؟ نحن في احتياج إلى نوع من التوازن الصحيح. لا يمكنك أن تجعل الجميع سعداء.

وقصة صغيرة أخرى تتعلق بتفاصيل حالتنا. بطريقة ما، تأخر العديد من الأشخاص عن الدرس العملي، ولسبب ما لم تبدأ الشرارة لهم. لقد نظرنا إلى كمية الموارد المجانية - يبدو أنها موجودة. يجب أن تبدأ الشرارة. لحسن الحظ، بحلول ذلك الوقت، تمت إضافة الوثائق بالفعل إلى القشرة الفرعية في مكان ما، وتذكرنا أنه عند إطلاقها، تبحث Spark عن منفذ للبدء منه. إذا كان المنفذ الأول في النطاق مشغولاً، فإنه ينتقل إلى المنفذ التالي بالترتيب. إذا كان مجانيا، فإنه يلتقط. وهناك معلمة تشير إلى الحد الأقصى لعدد المحاولات لذلك. الإعداد الافتراضي هو 16. وهذا العدد أقل من عدد الأشخاص في مجموعتنا في الفصل. وعليه، وبعد 16 محاولة، استسلمت سبارك وقالت إنني لا أستطيع البدء. لقد قمنا بتصحيح هذه المعلمة.

spark.port.maxRetries=50

بعد ذلك، سأخبرك ببعض الإعدادات التي لا ترتبط ارتباطًا وثيقًا بتفاصيل حالتنا.

لبدء تشغيل Spark بشكل أسرع، يوصى بأرشفة مجلد jars الموجود في الدليل الرئيسي SPARK_HOME ووضعه على HDFS. عندها لن يضيع الوقت في تحميل هذه الجرانيك من قبل العمال.

spark.yarn.archive=hdfs:///tmp/spark-archive.zip

يوصى أيضًا باستخدام kryo كمُسلسل لتشغيل أسرع. إنه أكثر تحسينًا من الافتراضي.

spark.serializer=org.apache.spark.serializer.KryoSerializer

وهناك أيضًا مشكلة طويلة الأمد مع Spark وهي أنها غالبًا ما تتعطل من الذاكرة. غالبًا ما يحدث هذا في الوقت الذي يقوم فيه العمال بحساب كل شيء وإرسال النتيجة إلى السائق. لقد جعلنا هذه المعلمة أكبر لأنفسنا. بشكل افتراضي، هو 1 غيغابايت، لقد جعلناه 3.

spark.driver.maxResultSize=3072

وأخيرًا كحلوى. كيفية تحديث Spark إلى الإصدار 2.1 على توزيع HortonWorks - HDP 2.5.3.0. يحتوي هذا الإصدار من HDP على الإصدار 2.0 المثبت مسبقًا، لكننا قررنا ذات مرة بأنفسنا أن Spark تتطور بشكل نشط للغاية، وكل إصدار جديد يعمل على إصلاح بعض الأخطاء بالإضافة إلى توفير ميزات إضافية، بما في ذلك واجهة برمجة تطبيقات python، لذلك قررنا ما الذي يجب علينا فعله يجب القيام به هو التحديث.

تم تنزيل الإصدار من الموقع الرسمي لـ Hadoop 2.7. قم بفك ضغطه ووضعه في مجلد HDP. لقد قمنا بتثبيت الروابط الرمزية حسب الحاجة. نطلقه - لا يبدأ. يكتب خطأ غير واضح للغاية.

java.lang.NoClassDefFoundError: com/sun/jersey/api/client/config/ClientConfig

بعد البحث على Google، اكتشفنا أن Spark قررت عدم الانتظار حتى ولادة Hadoop، وقررت استخدام الإصدار الجديد من القميص. إنهم هم أنفسهم يتجادلون مع بعضهم البعض حول هذا الموضوع في JIRA. وكان الحل للتحميل نسخة القميص 1.17.1. ضع هذا في مجلد الجرار في SPARK_HOME، واضغطه مرة أخرى وقم بتحميله على HDFS.

لقد تجاوزنا هذا الخطأ، ولكن ظهر خطأ جديد ومبسط إلى حد ما.

org.apache.spark.SparkException: Yarn application has already ended! It might have been killed or unable to launch application master

في الوقت نفسه، نحاول تشغيل الإصدار 2.0 - كل شيء على ما يرام. حاول تخمين ما يحدث. لقد بحثنا في سجلات هذا التطبيق ورأينا شيئًا مثل هذا:

/usr/hdp/${hdp.version}/hadoop/lib/hadoop-lzo-0.6.0.${hdp.version}.jar

بشكل عام، لسبب ما لم يتم حل hdp.version. وبعد البحث في جوجل وجدنا الحل. تحتاج إلى الانتقال إلى إعدادات YARN في Ambari وإضافة معلمة هناك إلى موقع الغزل المخصص:

hdp.version=2.5.3.0-37

وقد ساعد هذا السحر، وانطلقت سبارك. لقد اختبرنا العديد من أجهزة الكمبيوتر المحمولة jupyter الخاصة بنا. كل شيء يعمل. نحن مستعدون لدرس سبارك الأول يوم السبت (غدًا)!

UPD. أثناء الدرس، ظهرت مشكلة أخرى. في مرحلة ما، توقفت YARN عن توفير الحاويات لـSpark. في YARN كان من الضروري تصحيح المعلمة، والتي كانت افتراضيًا 0.2:

yarn.scheduler.capacity.maximum-am-resource-percent=0.8

أي أن 20% فقط من الموارد شاركت في توزيع الموارد. بعد تغيير المعلمات، قمنا بإعادة تحميل YARN. تم حل المشكلة وتمكن باقي المشاركين أيضًا من تشغيل سياق الشرارة.

المصدر: www.habr.com

إضافة تعليق