How we scaled async workload processing at GitLab.com using Sidekiq
Bài tóm tắt GitLab 2020 3. Quy mô lớn Độ khó: Trung bình
GitLab · 2020 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc
Bối cảnh
- GitLab (Rails) xử lý việc nền bằng Sidekiq trên Redis. Lịch sử: 2013 mỗi worker class một queue, không ai quản; 2016 gom theo tính năng; 2017 lại mỗi worker class một queue, gom thành nhóm
realtime,asap,besteffortđể giám sát và giới hạn từng queue. Tác giả Sidekiq khuyên không quá vài queue (M process poll N queue = O(M×N) thao tác/giây lên Redis); GitLab chấp nhận đánh đổi này gần hai năm. - Giữa 2019 có nhiều sự cố lớn quanh hàng đợi nền: gọi Gitaly n+1 làm queue phình; một user tạo rất nhiều note trên một commit làm chậm queue gửi thông báo; job xử lý pipeline dồn, node pipeline hết CPU, pool pgbouncer của Sidekiq bão hoà.
Thay đổi chính
- Trạng thái cũ: quan hệ nhiều-nhiều giữa job và role (một job chạy trên tới ba loại node); worker thread dành riêng cho từng queue (một phần tám fleet
realtimechonew_note: dồn job thì phần lớn fleet ngồi chơi, thêm node chỉ thêm một phần tám năng lực); job gấp và job chậm (tới 10 phút) chung một queue. - Sắp lại: mỗi job chạy trên đúng một role; mọi thread chạy mọi job của role nên dồn job thì dùng được 100% node; tách job nhanh và chậm. Nhưng đó là ảnh chụp một thời điểm, sẽ lỗi thời khi code đổi.
- Phân loại workload ngay trong code và dùng queue selector (chọn queue theo thuộc tính thay vì theo tên): developer khai báo urgency (
high/low/none), có phụ thuộc ngoài không (ví dụ cluster Kubernetes của user), cpu-bound hay memory-bound (quyết định mức đồng thời trong process Ruby, hoặc đưa job tốn RAM lên node ít thread nhiều RAM). - SLA tách trách nhiệm: job high chờ không quá 10 giây và chạy không quá 10 giây; low chờ không quá 1 phút; không urgency thì không SLA chờ; job không phải high chạy không quá 5 phút. SLA chờ là việc của đội hạ tầng (cấp đủ fleet), SLA chạy là việc của đội sở hữu worker.
- Redis: node
catchalltheo dõi khoảng 200 queue;besteffortcó 7 node × 8 process × 15 thread = 840 client cùngBRPOPtrên nhiều key, rất tốn thời gian theo chuẩn Redis. GitLab báo lỗi hiệu năng; antirez trả lời trong một giờ, có bản vá cùng ngày (Redis 6, backport Redis 5). - Xong chuyển selector cuối 4/2020: fleet Sidekiq từ 49 node/314 CPU xuống 26 node/158 CPU, utilization đều hơn. Sidekiq Cluster thành mặc định ở bản 13.0 để môi trường dev giống production. Tiếp theo: giảm số queue phải theo dõi.
Vì sao
- Mục tiêu chịu 100 lần traffic lúc đó và để vận hành "không bất ngờ": ai cũng hiểu job chạy ở đâu, vì sao dồn, làm sao giảm; hạ tầng không phải định tuyến job bằng tay theo sự cố.
Bài học cho SWE
- Dành thread cố định cho từng queue làm fleet không co giãn được khi một loại job bùng nổ.
- Đừng trộn job gấp với job chậm trong cùng hàng đợi ("làn 10 món" phải được giữ).
- Đẩy thông tin về workload vào khai báo của chính job để định tuyến tự động khỏi lỗi thời.
- Nhiều queue × nhiều client có chi phí ẩn trên broker (ở đây là
BRPOPcủa Redis).
Liên quan
- Event-driven, message queue và Kafka · Load shedding, rate limit và backpressure
- Cron đầu phút và tải tự gây ra ở GitLab: GitLab 2019
#Sidekiq#Redis#BRPOP#queue#worker thread#Sidekiq role#queue selector#urgency#SLA hàng đợi#cpu-bound/memory-bound
Được nhắc tới trong
Công ty (1)