Hầu hết các ứng dụng đều cần các tác vụ chạy nền cho người gửi thư, dọn dẹp thường xuyên hoặc bất kỳ hoạt động tốn thời gian nào khác mà không yêu cầu người dùng phải có mặt.
Một số gem hỗ trợ job queue và xử lý nền trong thế giới Rails — Delayed Job và Sidekiq là hai loại phổ biến nhất.
Trong bài đăng này, chúng ta sẽ xem xét chi tiết về Delayed Job và Sidekiq, bao gồm cả cách chúng đối đầu với nhau.
Đi thôi!
Giới thiệu nhanh về công việc bị trì hoãn
Công việc bị trì hoãn là một trích xuất trực tiếp từ Shopify và sử dụng bảng để duy trì tất cả các công việc nền. Nó tuân theo một mẫu rất đơn giản. Bất kỳ đối tượng Ruby nào phản hồi perform phương thức có thể được xếp vào hàng đợi trong bảng công việc.
Ngoài ra, nếu bạn không cần duy trì các đối tượng công việc đặc biệt (mặc dù điều này rất được khuyến khích để kiểm tra và phân tách rõ ràng các hoạt động chạy dài), nó cũng cho phép bạn gọi .delay.method(params) trên bất kỳ đối tượng Ruby nào. Nó sẽ xử lý phương thức ở chế độ nền.
Công việc bị trì hoãn README giải thích rất tốt tất cả các kiểu sử dụng phổ biến.
Nhiều nhóm chọn Công việc bị trì hoãn vì nó đơn giản và sử dụng cơ sở dữ liệu đã có sẵn của họ. Họ không cần phải chi tiêu/duy trì các nguồn lực khác.
Tuy nhiên, nó vẫn sẽ chiếm dung lượng trong bảng cơ sở dữ liệu của bạn. Nếu bạn có quá nhiều công việc phải xếp hàng đợi cùng một lúc, bạn có thể cần thêm dung lượng ổ đĩa để chứa tất cả chúng.
Giới thiệu nhanh về Sidekiq
Mặt khác, Sidekiq sử dụng Redis làm kho lưu trữ dữ liệu để duy trì tất cả siêu dữ liệu công việc. Điều này mang lại lợi ích rõ ràng là nhanh hơn nhiều so với các hệ thống cơ sở dữ liệu thông thường mà Delayed Jobs sử dụng. Ngoài ra, mỗi quy trình Sidekiq còn tạo ra nhiều luồng để xử lý công việc nhanh hơn nữa.
Đối với mỗi công việc nền trong Sidekiq, chúng ta cần một lớp chuyên biệt bao gồm Sidekiq::Worker quan tâm và phản hồi perform phương thức. Để xử lý công việc, chúng ta cần gọi perform_async(arg1, arg2) trên công nhân với các đối số.
Hướng dẫn 'Bắt đầu' của Sidekiq giải thích điều này và các cách sử dụng khác một cách chi tiết.
Sử dụng công việc đang hoạt động với công việc bị trì hoãn hoặc Sidekiq
Rails đã cung cấp một khung công việc hoàn chỉnh để khai báo và xử lý các công việc ở cấp cao nhất. Cả Delayed Job và Sidekiq đều hỗ trợ chạy các công việc thông qua API hợp nhất của ActiveJob. Chỉ cần kế thừa từ ApplicationJob và gọi perform_later trên lớp công việc của bạn để đưa công việc vào hàng đợi phụ trợ đã định cấu hình.
Ưu điểm của việc chạy công việc với Active Job là mã ứng dụng của bạn trở thành bất khả tri về khung và việc chuyển từ Delayed Job sang Sidekiq (hoặc ngược lại) trở nên khá dễ dàng. ActiveJob::TestHelper cũng làm cho việc thử nghiệm các công việc xếp hàng trở nên dễ dàng.
Tuy nhiên, khả năng trừu tượng hóa do Active Job cung cấp cũng đi kèm với chi phí về hiệu suất, vì dữ liệu công việc phải được gói trước khi được đẩy vào cửa hàng. Sidekiq tuyên bố rằng ActiveJob chậm hơn khoảng 2-20 lần khi chuyển sang Redis, với chi phí xử lý ~3 lần.
Công việc bị trì hoãn so với Sidekiq
Bây giờ chúng ta đã biết những kiến thức cơ bản về Delayed Jobs và Sidekiq, hãy cùng tìm hiểu sâu hơn về sự khác biệt của chúng và lợi ích mà mỗi loại mang lại.
Tính năng
Đối với các ứng dụng cơ bản, cả Sidekiq và Delayed Job đều cung cấp một bộ tính năng tốt. Chúng bao gồm chỉ định mức độ ưu tiên công việc, hàng đợi được đặt tên và tự động thử lại khi có lỗi.
Delayed Job cũng cung cấp một cách để định cấu hình thời gian chạy tối đa ngay lập tức (Sidekiq thì không).
Mặt khác, Sidekiq cung cấp hỗ trợ cho Middleware để cập nhật siêu dữ liệu công việc, bỏ qua việc xếp hàng công việc hoặc thực thi công việc. Sidekiq hỗ trợ nhiều lệnh gọi lại hơn, mặc dù một số hook có sẵn cho ứng dụng Delayed Job. Thay vì gọi lại, bạn có thể sử dụng Công việc bị trì hoãn với Công việc đang hoạt động (cụ thể là before_enqueue và around_perform lệnh gọi lại có sẵn trong Rails).
Giao diện người dùng web là một tính năng khác xuất hiện trong Sidekiq. Tính năng này cung cấp số liệu thống kê lịch sử về công việc và thông tin về người lao động, công việc hiện đang được xếp hàng và công việc đã chết. Bạn có thể thực hiện các thao tác như xóa hoặc chạy công việc ngay lập tức mà không cần thông qua bảng điều khiển.
Công việc bị trì hoãn không có giao diện người dùng web sẵn có nhưng delayed_job_web cấp quyền truy cập vào giao diện người dùng Web cơ bản với các tính năng tương tự như của Sidekiq.
Sidekiq giành chiến thắng ở hiệu suất
Về mặt hiệu suất, Sidekiq đánh bại Delayed Job một cách khá thuyết phục. Theo điểm chuẩn nguồn mở của Sidekiq, nó nhanh hơn khoảng 30 lần so với Delayed Job. Có hai lý do chính cho điều này:
- Redis truy vấn dữ liệu nhanh hơn nhiều so với cơ sở dữ liệu truyền thống như Postgres vì nó lưu trữ dữ liệu trong bộ nhớ chứ không phải trên đĩa.
- Delayed Job chạy một luồng duy nhất để xử lý công việc, so với Sidekiq sử dụng nhiều luồng.
Mặc dù tất cả những điều này trông tuyệt vời trên giấy tờ, nhưng sự khác biệt không quan trọng lắm trừ khi bạn làm việc trên quy mô lớn (chẳng hạn như 10 nghìn công việc mỗi phút). Con số chính xác cũng phụ thuộc vào thời gian chạy trung bình của một công việc. Thời gian chạy càng dài thì chi phí hoạt động của Công việc bị trì hoãn càng ít quan trọng.
Nếu lo lắng về hiệu suất của Công việc bị trì hoãn, bạn có thể thực hiện một số tối ưu hóa hiệu suất. Các chỉ mục chính xác để sử dụng sẽ phụ thuộc vào số liệu thống kê của hệ thống công việc của bạn. Ví dụ:nếu bạn sử dụng nhiều hàng đợi và chỉ một hàng nhận được phần lớn công việc, thì một chỉ mục đơn giản trên cột hàng đợi (add_index :delayed_jobs, :queue ) có thể cải thiện đáng kể hiệu suất.
Trong AppSignal, bảng điều khiển ma thuật Sidekiq được tạo tự động và cho phép bạn theo dõi độ dài hàng đợi, độ trễ hàng đợi, thời lượng công việc, trạng thái công việc, mức sử dụng bộ nhớ, v.v.

Triển khai
Cả Delayed Job và Sidekiq đều có chiến lược triển khai tương tự cho công nhân. Khi sử dụng Heroku, bạn chỉ cần thêm các mục bên trong Procfile của mình để khởi động bộ xử lý công việc và chạy các công nhân.
Dành cho Sidekiq:
Đối với công việc bị trì hoãn:
Bộ nhớ
Đây là nơi mọi thứ bắt đầu trở nên thú vị hơn một chút. Sidekiq có tùy chọn đồng thời để kiểm soát số lượng luồng chạy. Hầu hết các điểm chuẩn của Sidekiq so với Delayed Job đều đề cập đến khả năng chạy đồng thời rất cao của Sidekiq lên tới 25 luồng, góp phần mang lại hiệu suất siêu nhanh.
Nhưng trong cài đặt thực, bạn phải giới hạn các luồng ở mức thận trọng hơn. Con số thực tế phụ thuộc vào mức độ nặng của ứng dụng của bạn và loại công việc bạn thực hiện. Điều tôi đã thấy trong thực tế là nếu bạn chạy một worker trên bộ nhớ 512MB (tương đương với standard-1x trên Heroku), số lượng chủ đề nằm trong khoảng từ 2 đến 5 thay vì 25.
'Taming Rails Memory bloat' của Mike Perham, người tạo ra Sidekiq, thảo luận chi tiết hơn về các vấn đề về bộ nhớ và rất đáng đọc. Tôi sẽ không đi sâu vào cuộc thảo luận đầy đủ nhưng anh ấy khuyên bạn nên đặt MALLOC_ARENA_MAX=2 trên tất cả công nhân chạy Sidekiq.
Sử dụng jemalloc thay vì malloc thông thường cũng giúp ích. Cách chính xác để thực hiện việc này tùy thuộc vào nền tảng bạn sử dụng, nhưng nó khá đơn giản trên Heroku. Chỉ cần đặt heroku-buildpack-jemalloc làm gói xây dựng đầu tiên (trước heroku/ruby gói xây dựng).
Công việc bị trì hoãn sử dụng tài nguyên đơn giản hơn
Như chúng ta đã thảo luận, Công việc bị trì hoãn chạy trên phiên bản cơ sở dữ liệu hiện có của bạn. Bạn có thể cần tăng:
- bộ nhớ khả dụng
- dung lượng ổ đĩa
- kết nối tối đa
tùy theo khối lượng công việc hoặc số lượng công nhân bạn điều hành. Nhưng tài nguyên duy nhất bạn cần là bộ xử lý công việc.
Mặt khác, Sidekiq yêu cầu một phiên bản Redis để xử lý các công việc. Nếu bạn cũng sử dụng Redis làm kho lưu trữ bộ đệm, bạn nên sử dụng một phiên bản riêng được định cấu hình làm "kho lưu trữ liên tục" cho các công việc Sidekiq.
Vì Redis hoạt động tốt nhất khi mọi thứ đều nằm trong bộ nhớ, nên nếu bạn có quá nhiều tác vụ (ví dụ:nếu Sidekiq ngừng xử lý chúng trong một thời gian do sự cố trong ứng dụng), thì có thể phải mất một khoảng thời gian ngừng hoạt động để xóa mọi thứ. Điều này đặc biệt rắc rối nếu bạn có Redis trên cùng một máy chủ với ứng dụng của bạn. Chúng sẽ bắt đầu cạnh tranh giành bộ nhớ, dẫn đến hoán đổi và cuối cùng phá hủy hiệu suất ứng dụng của bạn.
Một điểm quan trọng cần lưu ý về Redis là nó phải được cấu hình bằng maxmemory-policy noeviction để tránh làm rơi dữ liệu của Sidekiq trong im lặng. Nếu không, bạn sẽ thấy mình thiếu những công việc cần thực hiện mà không có bất kỳ dấu vết nào.
Lưu ý phụ:Nâng cấp trả phí trong Sidekiq
Nếu bạn cần các tính năng bổ sung, Sidekiq đi kèm với Pro và Enterprise phiên bản.
Sự bổ sung đáng chú ý nhất cho Pro là Batch Jobs có thể chạy song song, được giám sát và tương tác như một nhóm, gọi lại khi tất cả công việc được thực hiện. Pro cũng đã cải thiện các tính năng về độ tin cậy để đảm bảo rằng không có công việc nào bị hủy bỏ một cách âm thầm, ngay cả khi có sự cố mạng.
Phiên bản Enterprise đi kèm với nhiều tính năng hơn. Nếu bạn đang tìm kiếm thứ gì đó mà việc cài đặt Sidekiq thông thường không thể giải quyết được, hãy khám phá các tính năng Sidekiq trả phí.
Trên thực tế, phiên bản miễn phí của Sidekiq vẫn hoạt động tốt. Nhưng thật tốt khi biết rằng có những tùy chọn trả phí mà bạn có thể nâng cấp lên khi cần, thay vì chuyển sang một giải pháp khác.
Tình trạng phát triển và cộng đồng:Sidekiq có lợi thế
Có một cộng đồng lớn đằng sau cả Sidekiq và Delayed Job. Tuy nhiên, không phải lúc nào cũng dễ dàng tìm thấy câu trả lời nhanh cho câu hỏi của bạn trong StackOverflow hoặc tài liệu chính thức.
Về mặt phát triển, mọi thứ có vẻ không mấy sáng sủa đối với Delayed Job. Đã có một số công việc nhỏ được thực hiện đối với Delayed Job vào tháng 12 năm 2021 và tháng 1 năm 2022, nhưng có vẻ như nó sẽ không có bất kỳ sự phát triển lớn nào trong tương lai. Có vẻ như nó đang ở chế độ chỉ bảo trì và có rất nhiều vấn đề còn tồn tại trên Github.
Ngược lại, Sidekiq vẫn đang được phát triển tích cực và người tạo ra nó đang làm việc toàn thời gian. Có rất ít vấn đề còn tồn tại và chúng được giải quyết thường xuyên.
Tóm tắt:Sidekiq hay công việc bị trì hoãn? Nó phụ thuộc vào nhu cầu của bạn
Trong bài đăng này, chúng tôi đã đề cập đến hai hệ thống xử lý công việc chính cho các ứng dụng Rails — Sidekiq và Delayed Job — xem xét một số ưu và nhược điểm của chúng.
Có những trường hợp sử dụng khác nhau cho mỗi. Tất cả phụ thuộc vào ngân sách và quy mô hoạt động của bạn.
Nếu hiệu suất và khả năng bảo trì lâu dài là quan trọng thì Sidekiq là lựa chọn không cần bàn cãi. Mặt khác, nếu bạn lo ngại về chi phí vận hành thì Delayed Job có thể giúp bạn điều đó.
Cho dù bạn chọn Delayed Job hay Sidekiq, chúc bạn may mắn với dự án của mình và viết mã vui vẻ!
👋 Nếu bạn thích bài viết này, hãy xem các bài viết khác về hiệu suất Ruby (on Rails) trong danh sách kiểm tra giám sát hiệu suất Ruby của chúng tôi.
Tái bút. Nếu bạn muốn đọc các bài đăng của Ruby Magic ngay khi chúng được đăng tải, hãy đăng ký nhận bản tin Ruby Magic của chúng tôi và không bao giờ bỏ lỡ một bài đăng nào!