Dành cho ai
Bạn viết Go, và service chạy trên một máy Linux duy nhất dưới systemd. Có thể đó là một API kèm worker nền và SQLite, một bộ nhận webhook, hoặc công cụ nội bộ mà cả công ty đang dựa vào. Nó chạy ổn. Điều bạn muốn biết là chuyện gì xảy ra ở các biên: deploy lúc request còn đang xử lý dở, một client mãi không gửi xong header, một container thiếu bộ nhớ, một cú crash lúc 3 giờ sáng.
Đây không phải sách dạy Go. Nó giả định bạn đã biết ngôn ngữ và đã đưa thứ gì đó lên production. Nếu bạn đang tìm phần nhập môn về goroutine, mấy cuốn sách Go nổi tiếng là chỗ bắt đầu tốt hơn.
Trong sách có gì
Một cuốn 16 chương, khoảng 2,000 dòng, cùng một service tham chiếu nhỏ, là nguồn của mọi đoạn code Go trong sách. Một script kiểm tra từng khối trong 60 khối code có khớp với source đã test hay không, nên không có đoạn nào trong sách là snippet chưa ai chạy.
| # | Chương |
|---|---|
| 1 | Cấu trúc dự án cho một service nhỏ |
| 2 | Config từ biến môi trường: kiểm tra mọi thứ, lỗi thì dừng ngay |
| 3 | Structured logging với log/slog mà không lộ secret |
| 4 | Timeout của HTTP server |
| 5 | Graceful shutdown |
| 6 | Health và readiness khác nhau thế nào |
| 7 | Context, hủy tác vụ và cách bắt goroutine leak |
| 8 | Truy cập database với SQLite: WAL, một writer, migration |
| 9 | Lỗi và panic |
| 10 | Metrics và pprof, theo cách an toàn |
| 11 | Viết test |
| 12 | Build: binary tĩnh, build lặp lại ra kết quả y hệt |
| 13 | systemd: unit, siết bảo mật, restart, stop |
| 14 | Bộ nhớ: process Go làm gì khi bị ép |
| 15 | Deploy bằng thư mục release |
| 16 | Các bug production hay gặp, mỗi bug kèm một phép kiểm tra bắt được nó |
Bạn còn có service tham chiếu (thư viện chuẩn cộng một driver SQLite), một công cụ tạo tải, một thí nghiệm nhỏ về bộ nhớ, systemd unit và Dockerfile, ba checklist, và một harness Docker chạy lại mọi phép kiểm tra từ container sạch. Kết quả lần chạy đầy đủ gần nhất cũng có sẵn để bạn so.
Test cho thấy gì
Các chương về shutdown và systemd có test đi kèm: test khởi động binary thật và gửi signal thật.
| Việc đã làm | Kết quả |
|---|---|
| SIGTERM khi một job 1.5 s đang chạy dở | Kết nối mới bị từ chối sau 11 ms, request đang xử lý xong sau 1.399 s, process thoát với code 0 sau 1.669 s |
| SIGTERM gửi tới service đang rảnh | Thoát sau 2 ms |
| SIGTERM khi có job 9 s và giới hạn shutdown 500 ms | Thoát sau 515 ms với code 1, job được trả lại queue |
| Client gửi header chậm, header timeout 300 ms | Kết nối bị cắt sau 295 ms |
systemctl stop khi một request 3 s đang chạy | Request trả 200, lệnh stop mất 3.19 s |
kill -9 dưới systemd | Khỏe lại sau 2.10 s |
| Hai lần build từ hai thư mục khác nhau | Binary giống nhau từng byte (và khác nhau khi bỏ -trimpath, làm đối chứng) |
systemd unit đi kèm các tùy chọn siết bảo mật, và chúng tôi đọc kết quả ngược lại từ process đang chạy thay vì tin vào file: không có capability nào, có bộ lọc seccomp, /usr và /etc chỉ đọc, có giới hạn bộ nhớ. systemd-analyze security chấm unit này 1.4 điểm mức độ phơi nhiễm.
Thông lượng và bộ nhớ
Cách đo: Docker Desktop trên laptop Apple Silicon, 8 CPU, service, công cụ tạo tải và database nằm trong một container, 16 client, ba lần chạy 8 giây cho mỗi chế độ.
| Chế độ | Request mỗi giây (3 lần chạy) |
|---|---|
| Ghi | 9,190 đến 11,189 (p99 từ 8.4 đến 11.7 ms) |
| Đọc | 13,541 đến 18,421 |
| Endpoint health | 23,032 đến 26,757 |
Bộ nhớ resident là 13 MiB lúc rảnh và 23 MiB sau khi chạy tải, đỉnh là 25 MiB.
GOMEMLIMIT, có số đo
Chương 14 không dừng ở câu "hãy đặt GOMEMLIMIT". Nó chạy một chương trình nhỏ có heap sống 40 MiB trong container bị giới hạn 80 MiB. Không đặt giới hạn thì bị OOM kill cả 3 trong 3 lần chạy. Đặt GOMEMLIMIT=56MiB thì sống sót 3 trong 3 lần, với cái giá là số lần garbage collection tăng khoảng gấp bốn. Sách cũng giải thích vì sao giới hạn này là giới hạn mềm và điều đó ảnh hưởng thế nào đến cách chọn kích thước.
Yêu cầu và định dạng
Go 1.24 trở lên. Chỉ cần Docker nếu bạn muốn chạy lại harness. Mọi thứ là Markdown, source Go, shell và file config: không khóa PDF, không cần tài khoản, đọc ở đâu cũng được.
Câu hỏi hay gặp
Đây có phải sách cho người mới không?
Không. Sách giả định bạn đã viết Go. Nội dung xoay quanh phía production: process làm gì khi có chuyện.
Có nói về Postgres không?
Service tham chiếu và các test của nó dùng SQLite. Chương về database cũng có hướng dẫn cho Postgres.
Nó khác gì Go Webhook Receiver Starter?
Starter là một sản phẩm nhỏ để bạn chạy. Sổ tay này là phần lập luận và test đằng sau một service Go cư xử đàng hoàng, dùng một service tham chiếu khác.
Tôi dùng code trong dự án của mình được không?
Được, trong dự án của bạn và trên server của bạn hoặc của công ty bạn. Xin đừng bán lại hay phân phối lại cuốn sách hoặc bộ kit.
Lịch sử thay đổi
- 0.1.0: bản đầu tiên.
Bài liên quan
- Graceful shutdown for a Go HTTP server under systemd (tiếng Anh)
- GOMEMLIMIT in an 80 MB container, with the numbers (tiếng Anh)
- Go SQLite reads returning 404 for rows that exist (tiếng Anh)
- log/slog setup for a small Go service on journald (tiếng Anh)
- Go HTTP server timeouts that survive slow and stuck clients (tiếng Anh)
Mua sản phẩm này
Polar lo thanh toán, thuế và hóa đơn (họ là merchant of record). Thanh toán xong bạn nhận link tải ngay.