Định cấu hình Spark trên YARN

Habr, xin chào! Hôm qua trên cuộc gặp gỡ dành riêng cho Apache Spark, từ các anh của Rambler&Co, đã có khá nhiều câu hỏi của người tham gia liên quan đến việc cấu hình công cụ này. Chúng tôi quyết định đi theo bước chân của anh ấy và chia sẻ kinh nghiệm của mình. Chủ đề này không hề dễ dàng - vì vậy chúng tôi mời bạn chia sẻ kinh nghiệm của mình trong phần bình luận, có thể chúng tôi cũng hiểu và sử dụng sai điều gì đó.

Giới thiệu một chút về cách chúng tôi sử dụng Spark. Chúng tôi có chương trình ba tháng “Chuyên gia dữ liệu lớn”và trong suốt mô-đun thứ hai, những người tham gia của chúng tôi sẽ làm việc trên nhạc cụ này. Theo đó, nhiệm vụ của chúng tôi, với tư cách là người tổ chức, là chuẩn bị cụm để sử dụng trong trường hợp đó.

Điểm đặc biệt trong việc sử dụng của chúng tôi là số lượng người làm việc đồng thời trên Spark có thể bằng cả nhóm. Ví dụ, tại một buổi hội thảo, khi mọi người cùng cố gắng làm một việc gì đó và lặp lại theo giáo viên của chúng ta. Và con số này không nhiều - đôi khi lên tới 40 người. Có lẽ không có nhiều công ty trên thế giới gặp phải trường hợp sử dụng như vậy.

Tiếp theo, tôi sẽ cho bạn biết cách thức và lý do chúng tôi chọn các thông số cấu hình nhất định.

Hãy bắt đầu lại từ đầu. Spark có 3 tùy chọn để chạy trên một cụm: độc lập, sử dụng Mesos và sử dụng YARN. Chúng tôi quyết định chọn phương án thứ ba vì nó có ý nghĩa đối với chúng tôi. Chúng tôi đã có một cụm hadoop. Những người tham gia của chúng tôi đã quen với kiến ​​trúc của nó. Hãy sử dụng YARN.

spark.master=yarn

Hơn nữa thú vị hơn. Mỗi tùy chọn triển khai trong số 3 tùy chọn này đều có 2 tùy chọn triển khai: máy khách và cụm. Dựa trên tài liệu và các liên kết khác nhau trên Internet, chúng tôi có thể kết luận rằng máy khách phù hợp với công việc tương tác - ví dụ: thông qua sổ ghi chép jupyter và cụm phù hợp hơn cho các giải pháp sản xuất. Trong trường hợp của chúng tôi, chúng tôi quan tâm đến công việc tương tác, do đó:

spark.deploy-mode=client

Nói chung, từ giờ trở đi Spark sẽ bằng cách nào đó hoạt động trên YARN, nhưng đối với chúng tôi điều này là chưa đủ. Vì chúng tôi có một chương trình về dữ liệu lớn nên đôi khi những người tham gia không có đủ những gì thu được trong khuôn khổ chia đều tài nguyên. Và sau đó chúng tôi tìm thấy một điều thú vị - phân bổ nguồn lực động. Tóm lại, vấn đề là thế này: nếu bạn gặp một nhiệm vụ khó khăn và cụm này trống (ví dụ: vào buổi sáng), thì việc sử dụng tùy chọn này Spark có thể cung cấp cho bạn thêm tài nguyên. Sự cần thiết được tính toán ở đó theo một công thức xảo quyệt. Chúng tôi sẽ không đi vào chi tiết - nó hoạt động tốt.

spark.dynamicAllocation.enabled=true

Chúng tôi đặt tham số này và khi khởi động Spark bị lỗi và không khởi động. Đúng rồi, vì tôi phải đọc nó tài liệu cẩn thận hơn. Nó nói rằng để mọi thứ đều ổn, bạn cũng cần kích hoạt một tham số bổ sung.

spark.shuffle.service.enabled=true

Tại sao nó lại cần thiết? Khi công việc của chúng ta không còn cần nhiều tài nguyên nữa, Spark nên đưa chúng trở lại nhóm chung. Giai đoạn tốn nhiều thời gian nhất trong hầu hết mọi nhiệm vụ MapReduce là giai đoạn Shuffle. Tham số này cho phép bạn lưu dữ liệu được tạo ở giai đoạn này và giải phóng các trình thực thi tương ứng. Và người thực thi là quá trình tính toán mọi thứ trên công nhân. Nó có một số lõi xử lý nhất định và một lượng bộ nhớ nhất định.

Tham số này đã được thêm vào. Mọi thứ dường như đã thành công. Điều đáng chú ý là những người tham gia thực sự được cung cấp nhiều tài nguyên hơn khi họ cần. Nhưng một vấn đề khác lại nảy sinh - đến một lúc nào đó, những người tham gia khác thức dậy và cũng muốn sử dụng Spark, nhưng ở đó mọi thứ đều bận rộn và họ không hài lòng. Chúng có thể được hiểu. Chúng tôi bắt đầu xem xét tài liệu. Hóa ra có một số thông số khác có thể được sử dụng để tác động đến quá trình. Ví dụ: nếu người thực thi ở chế độ chờ thì tài nguyên có thể được lấy từ nó sau bao lâu?

spark.dynamicAllocation.executorIdleTimeout=120s

Trong trường hợp của chúng tôi, nếu người thi hành của bạn không làm gì trong hai phút thì vui lòng đưa họ trở lại nhóm chung. Nhưng thông số này không phải lúc nào cũng đủ. Rõ ràng là người đó đã không làm gì trong một thời gian dài và tài nguyên cũng không được giải phóng. Hóa ra cũng có một tham số đặc biệt - sau thời gian nào để chọn bộ thực thi có chứa dữ liệu được lưu trong bộ nhớ cache. Theo mặc định, tham số này là vô cùng! Chúng tôi đã sửa nó.

spark.dynamicAllocation.cachedExecutorIdleTimeout=600s

Nghĩa là, nếu người thi hành án của bạn không làm gì trong 5 phút, hãy đưa họ vào nhóm chung. Ở chế độ này, tốc độ giải phóng và cấp tài nguyên cho số lượng lớn người dùng đã trở nên khá tốt. Mức độ bất mãn đã giảm đi. Nhưng chúng tôi đã quyết định đi xa hơn và giới hạn số lượng người thực thi tối đa cho mỗi ứng dụng - về cơ bản là cho mỗi người tham gia chương trình.

spark.dynamicAllocation.maxExecutors=19

Tất nhiên, bây giờ ở phía bên kia có những người không hài lòng - "cụm không hoạt động và tôi chỉ có 19 người thực thi", nhưng bạn có thể làm gì? Chúng ta cần một số loại cân bằng chính xác. Bạn không thể làm cho tất cả mọi người hạnh phúc.

Và một câu chuyện nhỏ nữa liên quan đến chi tiết vụ án của chúng tôi. Bằng cách nào đó, một số người đã đến muộn trong buổi học thực tế và vì lý do nào đó Spark đã không bắt đầu cho họ. Chúng tôi đã xem xét số lượng tài nguyên miễn phí - có vẻ như nó ở đó. Spark nên bắt đầu. May mắn thay, vào thời điểm đó tài liệu đã được thêm vào vỏ não ở đâu đó và chúng tôi nhớ rằng khi khởi chạy, Spark sẽ tìm kiếm một cổng để bắt đầu. Nếu cổng đầu tiên trong phạm vi bận, nó sẽ chuyển sang cổng tiếp theo theo thứ tự. Nếu nó miễn phí, nó sẽ nắm bắt. Và có một tham số cho biết số lần thử tối đa cho việc này. Mặc định là 16. Con số này ít hơn số người trong nhóm chúng tôi trong lớp. Theo đó, sau 16 lần thử, Spark đã bỏ cuộc và nói rằng tôi không thể bắt đầu được. Chúng tôi đã sửa cài đặt này.

spark.port.maxRetries=50

Tiếp theo tôi sẽ cho bạn biết về một số cài đặt không liên quan nhiều đến chi tiết cụ thể trong trường hợp của chúng tôi.

Để khởi động Spark nhanh hơn, bạn nên lưu trữ thư mục jars nằm trong thư mục chính SPARK_HOME và đặt nó trên HDFS. Sau đó, anh ta sẽ không lãng phí thời gian để công nhân tải những chiếc bình này.

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

Bạn cũng nên sử dụng kryo làm bộ nối tiếp để hoạt động nhanh hơn. Nó được tối ưu hóa hơn so với mặc định.

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

Và còn một vấn đề tồn tại từ lâu với Spark đó là nó hay bị treo từ bộ nhớ. Thường thì điều này xảy ra vào thời điểm công nhân đã tính toán xong mọi việc và gửi kết quả cho tài xế. Chúng tôi đã làm cho thông số này lớn hơn cho chính mình. Theo mặc định, nó là 1GB, chúng tôi đã tạo thành 3.

spark.driver.maxResultSize=3072

Và cuối cùng, như một món tráng miệng. Cách cập nhật Spark lên phiên bản 2.1 trên bản phân phối HortonWorks - HDP 2.5.3.0. Phiên bản HDP này chứa phiên bản 2.0 được cài đặt sẵn, nhưng chúng tôi đã từng tự quyết định rằng Spark đang phát triển khá tích cực và mỗi phiên bản mới đều sửa một số lỗi và cung cấp các tính năng bổ sung, bao gồm cả API python, vì vậy chúng tôi đã quyết định những gì cần phải làm được thực hiện là một bản cập nhật.

Đã tải xuống phiên bản từ trang web chính thức cho Hadoop 2.7. Giải nén và cho vào thư mục HDP. Chúng tôi đã cài đặt các liên kết tượng trưng khi cần thiết. Chúng tôi khởi chạy nó - nó không bắt đầu. Viết một lỗi rất không rõ ràng.

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

Sau khi tìm kiếm trên Google, chúng tôi phát hiện ra rằng Spark đã quyết định không đợi cho đến khi Hadoop ra đời mà quyết định sử dụng phiên bản jersey mới. Chính họ cũng tranh luận với nhau về chủ đề này trong JIRA. Giải pháp là tải xuống phiên bản áo đấu 1.17.1. Đặt cái này vào thư mục jars trong SPARK_HOME, nén lại và tải nó lên HDFS.

Chúng tôi đã khắc phục được lỗi này nhưng lại xuất hiện một lỗi mới và khá hợp lý.

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

Đồng thời, chúng tôi thử chạy phiên bản 2.0 - mọi thứ đều ổn. Hãy thử đoán xem chuyện gì đang xảy ra. Chúng tôi đã xem xét nhật ký của ứng dụng này và thấy một cái gì đó như thế này:

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

Nói chung, vì lý do nào đó hdp.version không giải quyết được. Sau khi googling, chúng tôi tìm thấy một giải pháp. Bạn cần đi tới cài đặt YARN trong Ambari và thêm tham số ở đó vào trang sợi tùy chỉnh:

hdp.version=2.5.3.0-37

Phép thuật này đã giúp ích và Spark đã thành công. Chúng tôi đã thử nghiệm một số máy tính xách tay jupyter của chúng tôi. Mọi thứ đang hoạt động. Chúng ta đã sẵn sàng cho buổi học Spark đầu tiên vào thứ Bảy (ngày mai)!

CẬP NHẬT. Trong giờ học, một vấn đề khác lại được phát hiện. Tại một thời điểm nào đó, YARN đã ngừng cung cấp vùng chứa cho Spark. Trong YARN cần phải sửa tham số, theo mặc định là 0.2:

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

Tức là chỉ có 20% tài nguyên tham gia vào việc phân phối tài nguyên. Sau khi thay đổi các tham số, chúng tôi tải lại YARN. Sự cố đã được giải quyết và những người tham gia còn lại cũng có thể chạy bối cảnh tia lửa.

Nguồn: www.habr.com

Thêm một lời nhận xét