Lập trình 22/09/2026 6 phút

Protobuf wire format mổ đến từng byte: vì sao nó nhỏ hơn JSON 3,5 lần và message rỗng tốn 0 byte

Protobuf nhỏ hơn JSON không phải nhờ phép màu — mà nhờ ba quyết định thiết kế gọn gàng. Bài này dùng proto.Marshal rồi hexdump từng byte trong go-lab để giải mã: mỗi field là một tag (field_number dịch bit cộng wire_type) rồi tới value, số nguyên mã hoá bằng varint (số nhỏ chỉ 1 byte), và field mang giá trị mặc định không được ghi lên dây chút nào. Kết quả thật: cùng dữ liệu, JSON 46 byte còn Protobuf 13 byte, message rỗng tốn 0 byte.

Lập trình 22/09/2026 5 phút

Bốn kiểu RPC của gRPC: unary, server/client/bidirectional streaming — thứ REST không có sẵn

REST chỉ có một kiểu: một request, một response. gRPC có bốn, nhờ HTTP/2 cho phép streaming hai chiều ngay trong contract. Bài này chạy thật cả bốn trong go-lab: unary Double(21) trả 42; server streaming CountUp(5) trả về 5 message; client streaming SumAll gửi 4 nhận 1 (total=100); bidirectional RunningSum gửi/nhận xen kẽ 3 lần. Chỉ cần thêm từ khoá stream vào .proto, và biết khi nào dùng kiểu nào.

Lập trình 22/09/2026 6 phút

Tiến hoá schema Protobuf: vì sao field number là bất biến, và unknown field cứu dữ liệu qua tay service cũ

Protobuf nhận diện field bằng SỐ chứ không bằng tên — hiểu điều này là hiểu toàn bộ quy tắc tiến hoá schema. Bài này đo thật trong go-lab ba kịch bản: V1 ghi, V2 (thêm field) đọc được, field mới lấy default; V2 ghi có email, service V1 cũ đọc không thấy nhưng GIỮ LẠI email qua round-trip nhờ unknown field; và đổi field number khiến amount biến mất hoàn toàn. Rút ra luật quan trọng nhất của Protobuf.

Lập trình 22/09/2026 5 phút

Deadline và context trong gRPC: hạn chót lan truyền cả chuỗi gọi, và server dừng sớm để không phí tài nguyên

Một request không bao giờ nên treo vô hạn. gRPC gắn deadline vào context, gửi kèm request, để mọi tầng biết còn bao lâu và dừng đúng lúc. Bài này đo thật trong go-lab: call deadline 100ms vào handler làm 500ms trả về sau đúng 100ms với code DeadlineExceeded (không chờ hết việc); và server đọc ctx.Done() để dừng sớm thay vì chạy nốt 500ms vô ích. Hiểu cơ chế này để chống quá tải lan rộng.

Lập trình 22/09/2026 5 phút

Interceptor trong gRPC: middleware gắn một lần cho mọi RPC, và recover panic giữ server sống sót

Logging, auth, metrics, bắt panic — bạn không nhét chúng vào từng handler mà bọc quanh tất cả bằng interceptor, middleware của gRPC. Bài này đo thật trong go-lab: chain hai interceptor (log ngoài, recover trong) chạy lồng nhau như vỏ hành; một handler panic được interceptor recover bắt lại, client nhận lỗi Internal gọn gàng thay vì connection chết, và server vẫn phục vụ request tiếp theo bình thường.

Lập trình 22/09/2026 5 phút

Metadata và xác thực trong gRPC: truyền token như header HTTP, kiểm auth một chỗ cho mọi RPC

gRPC không có khái niệm header riêng — nó dùng metadata, cặp key-value gửi kèm mỗi request giống HTTP header. Bài này đo thật trong go-lab: client gắn token qua metadata.AppendToOutgoingContext, server đọc trong một interceptor auth tập trung. Gọi không token trả Unauthenticated, token sai trả PermissionDenied, token đúng mới cho handler chạy và server lấy được user=alice từ token. Và vì sao metadata bắt buộc chạy trên TLS.