Goodbye Microservices: From 100s of problem children to 1 superstar
Bài tóm tắt Segment 2018 4. Điều chỉnh Độ khó: Dễ
Segment · 2018 · 4. Điều chỉnh · Độ khó: Dễ — bài gốc
Bối cảnh
- Segment nhận hàng trăm nghìn event/giây và chuyển tiếp tới hơn 100 loại destination (Google Analytics, webhook…).
- Bước 1, một hàng đợi chung: event mới và event retry nằm chung. Một destination chậm thì retry ngập hàng đợi, gây head-of-line blocking: mọi destination đều trễ.
- Bước 2, microservices: mỗi destination có service + queue riêng, phía trước là router. Lỗi được cô lập, và thiết kế này đã giải đúng bài toán lúc đó.
- Bước 3, repo riêng: chung một repo thì một test hỏng chặn deploy mọi destination, nên tách mỗi destination một repo.
- Rồi vỡ:
- Thêm 50+ destination là thêm 50+ repo. Thư viện dùng chung được tạo ra, nhưng mỗi service dùng một phiên bản khác nhau vì không ai muốn deploy lại hàng chục service.
- Mỗi service có mẫu tải riêng, auto-scaling "là nghệ thuật hơn khoa học". Destination ít traffic phải scale tay khi có spike.
- Trung bình thêm 3 destination mỗi tháng, chi phí vận hành tăng tuyến tính. Cuối cùng 3 kỹ sư toàn thời gian chủ yếu chỉ giữ cho hệ thống sống.
Thay đổi chính
- Centrifuge thay cho 140+ hàng đợi riêng, đẩy event vào một service duy nhất.
- Monorepo, một phiên bản cho mỗi dependency (120 dependency), sửa mọi chỗ vỡ khi nâng cấp.
- Traffic Recorder (dựa trên yakbak): ghi lại request/response HTTP tới destination ở lần test đầu, các lần sau phát lại. Trước đó test gọi mạng thật nên chập chờn, mỗi destination có thể mất tới 5 phút, cả bộ tới 1 giờ. Sau: cả 140+ destination chạy trong mili giây.
- Gộp 140+ service thành một. Một kỹ sư deploy trong vài phút.
Kết quả
- Trước: 32 cải tiến thư viện chung. Một năm sau khi gộp: 46.
- Một pool worker lớn hấp thụ được spike, hết bị gọi dậy vì destination nhỏ.
Đánh đổi (Segment tự nêu)
- Mất cô lập lỗi: một bug crash service là crash mọi destination. Lúc viết bài họ dựa vào test tự động và đang làm một cơ chế chống lại việc này, chưa có lời giải.
- Cache trong bộ nhớ kém hiệu quả: dữ liệu control plane rải trên 3.000+ process nên ít hit. Họ chấp nhận, không thêm Redis.
- Nâng một dependency có thể làm vỡ nhiều destination. Họ chấp nhận vì đơn giản hơn, có test bắt lỗi.
Bài học cho SWE
- Microservices giải bài toán cô lập lỗi nhưng cần công cụ test/deploy hàng loạt; thiếu nó thì năng suất sụp đổ.
- Lý do tách ban đầu (cô lập test) hoá ra là lợi ích ảo: repo riêng làm mọi người không còn động lực sửa test hỏng.
- Phải xử lý được nguyên nhân gốc (test chập chờn, nhiều phiên bản dependency) thì mới gộp được.
- Segment nhấn mạnh: microservices vẫn hợp ở phần khác của hạ tầng họ. Đây là quyết định cho một thành phần.
Liên quan
Monolith và microservices — đi và quay lạiNền tảng nội bộ cho service (đường ray chung)Hot partition và thundering herd
Được nhắc tới trong
Chủ đề (3)
Công ty (1)