การกำหนดค่า Spark บน YARN

ฮาเบอร์ สวัสดี! เมื่อวาน มีตติ้งสำหรับ Apache Spark โดยเฉพาะจากทีมงานจาก Rambler&Co มีคำถามมากมายจากผู้เข้าร่วมที่เกี่ยวข้องกับการกำหนดค่าเครื่องมือนี้ เราตัดสินใจเดินตามรอยของเขาและแบ่งปันประสบการณ์ของเรา หัวข้อนี้ไม่ใช่เรื่องง่าย - ดังนั้นเราจึงขอเชิญคุณแบ่งปันประสบการณ์ของคุณในการแสดงความคิดเห็นบางทีเราอาจเข้าใจและใช้สิ่งผิดปกติด้วย

การแนะนำเล็กน้อยเกี่ยวกับวิธีที่เราใช้ Spark เรามีโปรแกรมสามเดือน “ผู้เชี่ยวชาญด้านข้อมูลขนาดใหญ่”และตลอดโมดูลที่สอง ผู้เข้าร่วมของเราก็จะใช้เครื่องมือนี้ ดังนั้นงานของเราในฐานะผู้จัดงานคือการเตรียมคลัสเตอร์เพื่อใช้ในกรณีดังกล่าว

ลักษณะเฉพาะของการใช้งานของเราคือจำนวนคนที่ทำงานบน Spark พร้อมกันสามารถเท่ากับทั้งกลุ่มได้ เช่น ในการสัมมนา เมื่อทุกคนพยายามทำบางอย่างพร้อมๆ กันและทำซ้ำตามอาจารย์ของเรา และนี่ก็ไม่มาก - บางครั้งมากถึง 40 คน อาจมีบริษัทไม่กี่แห่งในโลกที่เผชิญกับกรณีการใช้งานเช่นนี้

ต่อไป ฉันจะบอกคุณว่าเราเลือกพารามิเตอร์การกำหนดค่าบางอย่างอย่างไรและทำไม

เริ่มจากจุดเริ่มต้นกันก่อน Spark มี 3 ตัวเลือกในการทำงานบนคลัสเตอร์: แบบสแตนด์อโลน การใช้ Mesos และการใช้ YARN เราตัดสินใจเลือกตัวเลือกที่สามเพราะมันสมเหตุสมผลสำหรับเรา เรามีคลัสเตอร์ Hadoop อยู่แล้ว ผู้เข้าร่วมของเราคุ้นเคยกับสถาปัตยกรรมเป็นอย่างดีแล้ว มาใช้ YARN กันเถอะ

spark.master=yarn

ที่น่าสนใจยิ่งขึ้นไปอีก ตัวเลือกการปรับใช้ 3 ตัวเลือกเหล่านี้มี 2 ตัวเลือกการใช้งาน: ไคลเอ็นต์และคลัสเตอร์ ซึ่งเป็นรากฐาน เอกสาร และลิงก์ต่างๆ บนอินเทอร์เน็ต เราสามารถสรุปได้ว่าไคลเอ็นต์เหมาะสำหรับงานแบบโต้ตอบ เช่น ผ่านสมุดบันทึก jupyter และคลัสเตอร์เหมาะสำหรับโซลูชันการผลิตมากกว่า ในกรณีของเรา เราสนใจงานแบบโต้ตอบ ดังนั้น:

spark.deploy-mode=client

โดยทั่วไปจากนี้ไป Spark จะทำงานบน YARN บ้าง แต่ก็ยังไม่เพียงพอสำหรับเรา เนื่องจากเรามีโปรแกรมเกี่ยวกับข้อมูลขนาดใหญ่ บางครั้งผู้เข้าร่วมไม่ได้มีสิ่งที่ได้รับเพียงพอภายใต้กรอบของการแบ่งทรัพยากรอย่างเท่าเทียม แล้วเราก็พบสิ่งที่น่าสนใจ - การจัดสรรทรัพยากรแบบไดนามิก กล่าวโดยสรุป ประเด็นก็คือ: หากคุณมีงานที่ยากและคลัสเตอร์ว่าง (เช่น ในตอนเช้า) การใช้ตัวเลือก Spark นี้สามารถให้ทรัพยากรเพิ่มเติมแก่คุณได้ ความจำเป็นถูกคำนวณตามสูตรอันชาญฉลาด เราจะไม่ลงรายละเอียด - มันใช้ได้ดี

spark.dynamicAllocation.enabled=true

เราตั้งค่าพารามิเตอร์นี้และเมื่อเริ่มต้น Spark ก็ขัดข้องและไม่ได้เริ่มทำงาน ถูกต้องครับ เพราะผมต้องอ่านมัน เอกสาร ระวังมากขึ้น. โดยระบุว่าเพื่อให้ทุกอย่างเรียบร้อย คุณจะต้องเปิดใช้งานพารามิเตอร์เพิ่มเติมด้วย

spark.shuffle.service.enabled=true

เหตุใดจึงจำเป็น? เมื่องานของเราไม่ต้องการทรัพยากรมากมายอีกต่อไป Spark ควรส่งคืนทรัพยากรเหล่านั้นไปยังแหล่งรวมทั่วไป ขั้นตอนที่ใช้เวลานานที่สุดในเกือบทุกงาน MapReduce คือขั้นตอนการสุ่ม พารามิเตอร์นี้อนุญาตให้คุณบันทึกข้อมูลที่สร้างขึ้นในขั้นตอนนี้และปล่อยตัวดำเนินการตามนั้น และผู้ดำเนินการคือกระบวนการที่คำนวณทุกอย่างเกี่ยวกับผู้ปฏิบัติงาน มีแกนประมวลผลจำนวนหนึ่งและมีหน่วยความจำจำนวนหนึ่ง

เพิ่มพารามิเตอร์นี้แล้ว ทุกอย่างดูเหมือนจะทำงานได้ เห็นได้ชัดว่าผู้เข้าร่วมได้รับทรัพยากรมากขึ้นเมื่อพวกเขาต้องการ แต่มีปัญหาอีกอย่างเกิดขึ้น - เมื่อถึงจุดหนึ่งผู้เข้าร่วมคนอื่นตื่นขึ้นมาและต้องการใช้ Spark ด้วย แต่ทุกอย่างยุ่งอยู่ที่นั่นและพวกเขาก็ไม่มีความสุข พวกเขาสามารถเข้าใจได้ เราเริ่มดูเอกสาร ปรากฎว่ามีพารามิเตอร์อื่นๆ อีกหลายตัวที่สามารถใช้เพื่อส่งผลต่อกระบวนการได้ ตัวอย่างเช่น หากตัวดำเนินการอยู่ในโหมดสแตนด์บาย ทรัพยากรจะถูกนำไปใช้หลังจากเวลาใด?

spark.dynamicAllocation.executorIdleTimeout=120s

ในกรณีของเรา หากผู้ดำเนินการของคุณไม่ทำอะไรเป็นเวลาสองนาที โปรดส่งคืนพวกเขาไปที่กลุ่มรวม แต่พารามิเตอร์นี้ไม่เพียงพอเสมอไป เห็นได้ชัดว่าบุคคลนั้นไม่ได้ทำอะไรมาเป็นเวลานาน และทรัพยากรไม่ได้รับการปลดปล่อย ปรากฎว่ามีพารามิเตอร์พิเศษด้วย - หลังจากเวลาใดให้เลือกตัวดำเนินการที่มีข้อมูลแคช โดยค่าเริ่มต้น พารามิเตอร์นี้มีค่าอนันต์! เราแก้ไขมันแล้ว

spark.dynamicAllocation.cachedExecutorIdleTimeout=600s

นั่นคือหากผู้ดำเนินการของคุณไม่ทำอะไรเลยเป็นเวลา 5 นาทีให้ส่งพวกเขาไปที่พูลทั่วไป ในโหมดนี้ ความเร็วในการปล่อยและออกทรัพยากรสำหรับผู้ใช้จำนวนมากมีความเหมาะสม ความไม่พอใจก็ลดลง แต่เราตัดสินใจที่จะดำเนินการต่อไปและจำกัดจำนวนผู้ดำเนินการสูงสุดต่อแอปพลิเคชัน - โดยพื้นฐานแล้วต่อผู้เข้าร่วมโปรแกรม

spark.dynamicAllocation.maxExecutors=19

แน่นอนว่าตอนนี้มีคนไม่พอใจในอีกด้านหนึ่ง -“ คลัสเตอร์ไม่ได้ใช้งานและฉันมีเพียง 19 คนเท่านั้น” แต่คุณจะทำอย่างไร เราต้องการความสมดุลที่ถูกต้อง คุณไม่สามารถทำให้ทุกคนมีความสุขได้

และอีกเรื่องเล็กๆ น้อยๆ ที่เกี่ยวข้องกับกรณีเฉพาะของเรา มีคนหลายคนมาเรียนภาคปฏิบัติสาย และด้วยเหตุผลบางอย่าง Spark จึงไม่เริ่มสอนให้พวกเขา เราดูจำนวนทรัพยากรฟรี - ดูเหมือนว่าจะมีอยู่ สปาร์คควรเริ่มต้น โชคดีที่เมื่อถึงเวลานั้น เอกสารได้ถูกเพิ่มไปยัง subcortex ที่ไหนสักแห่งแล้ว และเราจำได้ว่าเมื่อเปิดตัว Spark จะมองหาพอร์ตที่จะเริ่มต้น หากพอร์ตแรกในช่วงไม่ว่าง พอร์ตนั้นจะย้ายไปยังพอร์ตถัดไปตามลำดับ ถ้ามันฟรีมันก็จับ และมีพารามิเตอร์ที่ระบุจำนวนครั้งสูงสุดในการดำเนินการนี้ ค่าเริ่มต้นคือ 16 จำนวนน้อยกว่าจำนวนคนในกลุ่มของเราในชั้นเรียน ดังนั้น หลังจากพยายาม 16 ครั้ง Spark จึงยอมแพ้และบอกว่าฉันเริ่มไม่ได้ เราได้แก้ไขพารามิเตอร์นี้แล้ว

spark.port.maxRetries=50

ต่อไป ฉันจะบอกคุณเกี่ยวกับการตั้งค่าบางอย่างที่ไม่เกี่ยวข้องกับข้อมูลเฉพาะของกรณีของเรามากนัก

หากต้องการเริ่ม Spark เร็วขึ้น ขอแนะนำให้เก็บถาวรโฟลเดอร์ jars ที่อยู่ในโฮมไดเร็กทอรี SPARK_HOME และวางไว้บน HDFS จากนั้นเขาจะไม่เสียเวลาโหลด jarniks เหล่านี้โดยคนงาน

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

ขอแนะนำให้ใช้ kryo เป็นตัวซีเรียลไลเซอร์เพื่อการทำงานที่รวดเร็วยิ่งขึ้น ได้รับการปรับให้เหมาะสมมากกว่าค่าเริ่มต้น

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

และยังมีปัญหาอันยาวนานกับ Spark ที่มักจะขัดข้องจากหน่วยความจำ บ่อยครั้งสิ่งนี้จะเกิดขึ้นในขณะที่คนงานคำนวณทุกอย่างแล้วส่งผลไปให้คนขับ เราทำให้พารามิเตอร์นี้ใหญ่ขึ้นสำหรับตัวเราเอง โดยค่าเริ่มต้นคือ 1GB เราสร้างเป็น 3

spark.driver.maxResultSize=3072

และสุดท้ายเป็นของหวาน วิธีอัปเดต Spark เป็นเวอร์ชัน 2.1 บนการกระจาย HortonWorks - HDP 2.5.3.0 HDP เวอร์ชันนี้มีเวอร์ชัน 2.0 ที่ติดตั้งไว้ล่วงหน้า แต่ครั้งหนึ่งเราตัดสินใจด้วยตัวเองแล้วว่า Spark กำลังพัฒนาค่อนข้างแข็งขัน และแต่ละเวอร์ชันใหม่จะแก้ไขข้อบกพร่องบางประการพร้อมทั้งมอบคุณสมบัติเพิ่มเติม รวมถึงสำหรับ python API ดังนั้นเราจึงตัดสินใจว่า จะต้องทำอะไร จะทำเสร็จแล้วคือการอัปเดต

ดาวน์โหลดเวอร์ชันจากเว็บไซต์อย่างเป็นทางการสำหรับ Hadoop 2.7 แตกไฟล์แล้วนำไปไว้ในโฟลเดอร์ HDP เราติดตั้ง symlink ตามความจำเป็น เราเปิดตัว - มันไม่เริ่ม เขียนข้อผิดพลาดที่ไม่ชัดเจนมาก

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

หลังจาก googling เราพบว่า Spark ตัดสินใจที่จะไม่รอจนกว่า Hadoop จะถือกำเนิด และตัดสินใจใช้เสื้อแข่งเวอร์ชันใหม่ พวกเขาโต้เถียงกันเกี่ยวกับหัวข้อนี้ใน JIRA วิธีแก้ไขคือการดาวน์โหลด เสื้อแข่งเวอร์ชั่น 1.17.1. วางสิ่งนี้ลงในโฟลเดอร์ jars ใน SPARK_HOME จากนั้น zip อีกครั้งแล้วอัปโหลดไปยัง 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 ไม่สามารถแก้ไขได้ หลังจาก googling เราก็พบวิธีแก้ไข คุณต้องไปที่การตั้งค่า YARN ใน Ambari และเพิ่มพารามิเตอร์ที่นั่นใน YARN-site ที่กำหนดเอง:

hdp.version=2.5.3.0-37

เวทมนตร์นี้ช่วยได้ และสปาร์คก็เริ่มต้นขึ้น เราทดสอบแล็ปท็อป jupyter หลายเครื่องของเรา ทุกอย่างทำงานได้ เราพร้อมแล้วสำหรับบทเรียน Spark ครั้งแรกในวันเสาร์ (พรุ่งนี้)!

DUP. ระหว่างบทเรียน มีปัญหาอีกอย่างหนึ่งเกิดขึ้น เมื่อถึงจุดหนึ่ง YARN ก็หยุดให้บริการคอนเทนเนอร์สำหรับ Spark ใน YARN จำเป็นต้องแก้ไขพารามิเตอร์ ซึ่งโดยค่าเริ่มต้นคือ 0.2:

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

นั่นคือมีเพียง 20% ของทรัพยากรเท่านั้นที่มีส่วนร่วมในการแจกจ่ายทรัพยากร หลังจากเปลี่ยนพารามิเตอร์แล้ว เราก็โหลด YARN อีกครั้ง ปัญหาได้รับการแก้ไขแล้วและผู้เข้าร่วมที่เหลือก็สามารถเริ่มจุดประกายบริบทได้เช่นกัน

ที่มา: will.com

เพิ่มความคิดเห็น