Stack Overflow: How We Do Monitoring - 2018 Edition
Bài tóm tắt Stack Overflow 2018 3. Quy mô lớn Độ khó: Trung bình
Stack Overflow · 2018 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc
Bài 4 trong series của Nick Craver. Bài trước: Stack Overflow 2016; bài sau: Stack Overflow 2019.
Bối cảnh
Cuối 2018, Stack Overflow vẫn chạy ASP.NET MVC5 và đang chuyển sang .NET Core. Bài chia dữ liệu monitoring thành logs, metrics, health checks và profiling, rồi kể các công cụ (phần lớn tự viết và open source) dùng cho từng loại.
Thay đổi chính
- Logs:
- lỗi ứng dụng luôn được ghi, bằng StackExchange.Exceptional vào SQL Server;
- Redis, Elasticsearch, SQL Server ghi log ra đĩa local; log thiết bị mạng đưa vào Logstash + Kibana;
- mọi HTTP request public đi qua HAProxy được ghi tóm tắt (không cookie, không form) vào SQL Server columnstore. App gửi header thời gian (tổng ASP.NET; số lệnh và số ms cho SQL, Redis, HTTP, tag engine, Elasticsearch), HAProxy tách các header đó ra và đưa vào dòng syslog. Dịch vụ nhận syslog là Traffic Processing Service;
- theo tác giả, ý tưởng ghi log HTTP từ khoảng 2010 bị cả đội cho là lãng phí, nhưng hoá ra rất đáng: số SQL query của một request cho biết user đã đi sâu tới đâu trong code; khi connection pool dồn ứ thì lọc được mọi request của một server trong một khoảng thời gian;
- hiệu giữa thời gian HAProxy đo (
Tr) và thời gian ASP.NET tự đo cho biết request mất bao lâu trong OS và hàng đợi thread của IIS.
- Health check:
- health check của stackoverflow.com là trang chủ: tải master view kéo theo rất nhiều phụ thuộc, nên bắt được cả lỗi mà một endpoint kiểm tra riêng sẽ bỏ sót (họ đã gặp trường hợp một cache không reload làm hỏng thanh trên cùng của mọi trang);
- phải đặt
http-check expect 200, vì trang lỗi của ASP.NET cũ là một redirect 302 mà HAProxy mặc định coi là khoẻ; - phân biệt "tôi còn sống" với "tôi sẵn sàng phục vụ". Web server mới build, đi từ DRAIN (qua health check) mất 8–20 giây để sẵn sàng; đi từ MAINT (traffic dồn vào ngay khi khởi động) mất 2–3 phút vì thread pool bị đói;
- web server gọi thẳng từng tag engine (không qua HAProxy) và ping mỗi giây, lấy luôn thông tin lần cuối tag engine nạp dữ liệu từ DB;
- Fastly health check để failover lần lượt: ISP chính NY → ISP phụ NY → ISP chính Colorado → ISP phụ Colorado. Pingdom kiểm tra từ bên ngoài.
- Metrics và alert: Bosun (tự viết bằng Go, agent scollector, lưu trên OpenTSDB/HBase). Theo tác giả, HBase đòi nhiều phần cứng mạng hơn mức cần với lượng dữ liệu nhỏ; họ đã thử dùng SQL Server columnstore làm backend (50–100K metric/giây chỉ tốn khoảng 5% CPU) nhưng vài truy vấn cardinality cao quá nặng.
- Điểm tác giả thích nhất: chạy thử alert trên dữ liệu lịch sử để thấy nó sẽ bắn lúc nào trước khi bật.
- Phân cấp: lỗi nghiêm trọng (site offline theo Pingdom, tỉ lệ lỗi cao) gọi thẳng PagerDuty cho SRE on-call; lỗi khẩn (tạo Team lỗi, scheduled task lỗi) đẩy vào chat; còn lại gửi email, kèm sẵn truy vấn SQL/Elasticsearch để chi tiết và 10 lần alert gần nhất.
- Grafana (plugin Bosun) để xem lịch sử.
- Client timings: lấy navigation timing từ 5% request, lưu vào columnstore, xem phân vị 95. Theo tác giả, trang câu hỏi render trên server mất 18 ms (2018), nhưng chỉ tốc độ user cảm nhận mới quan trọng.
- MiniProfiler trên mọi trang: hiện thời gian render ở góc trang, mở ra được cây thời gian từng SQL, Redis, HTTP. Chạy trên mọi request; giữ 100 profile chậm nhất của mỗi route trong Redis (sorted set). ID của MiniProfiler được dùng làm Request ID, ghi cả vào log HAProxy và exception để nối các nguồn với nhau.
- Opserver: dashboard tự viết sau một lần SQL Server AlwaysOn báo xanh trong khi replica đã mấy ngày không nhận dữ liệu mới (thread pool HADR cạn, view trạng thái không còn cập nhật). Bài học: trạng thái lưu lại phải có timestamp; quá lâu không cập nhật thì coi là đỏ. Opserver hỏi trực tiếp từng node SQL thay vì tin node primary, và có thêm trang cho Redis, Elasticsearch, HAProxy (rút máy khỏi rotation), exception.
Vì sao
Theo tác giả, lúc Bosun ra đời (khoảng 2014) không công cụ nào làm đúng thứ họ cần. Tự viết thì có mọi lợi ích của hệ nội bộ "và cả mọi cái giá của nó": đến 2018 Bosun gần như chỉ được bảo trì vì thiếu người. Ông cũng thừa nhận metrics bị dùng quá ít trong app.
Bài học cho SWE
- Một cột "số lệnh + số ms cho mỗi dependency" trên mọi request là công cụ điều tra rẻ mà mạnh.
- Health check nên chạy qua đúng đường user đi; và trạng thái "khoẻ" không có timestamp thì không đáng tin.
- Tự viết công cụ quan sát cho phép làm đúng nhu cầu, nhưng sẽ có lúc thiếu người bảo trì.
Liên quan
#Bosun#OpenTSDB#Grafana#MiniProfiler#Opserver#Exceptional#HAProxy log#Columnstore#Health check#Client timings#PagerDuty#Request ID
Được nhắc tới trong
Công ty (1)