Điều kiện tiên quyết: Đây là Phần 10 của Khóa Học System Design. Mấy chương trước cắm đầu cắm cổ dựng giàn giáo cất nóc (architecture) — tới chương này tao sẽ chỉ cho mày cách banh mắt chui tọt vô ruột ngó ngoáy một cái hệ thống đang quẫy đạp sống nhăn và rà bắt mạch tận gốc ba cái bệnh hoạn ệch ạch (performance issues) chốn production.
Answer-first: Đồ nghề mỏ hàn pprof (profiler) đúc liền xương tủy của Go dâng tận răng ngón nghề nhấp nháp nếm CPU (CPU sampling), mổ bụng săm soi đống mỡ phân lô (heap allocation analysis), lật nệm soi vết xếp chồng goroutine (goroutine stack inspection), và chỉ điểm ổ kẹt ngẽn (blocking profiler) — bưng bít sẵn sàng phơi ra như mấy cái cổng HTTP endpoints nhởn nhơ móc từ ba cái ổ dịch vụ production đang chạy ro ro mà cực kỳ héo hao tí tẹo tài nguyên (minimal overhead). Trò vác 2 bức hình chụp đống rác RAM (heap) ra cân đo đong đếm so lệch (Heap diff) là chiêu độc trị dứt điểm nhanh gọn lẹ lòi mặt chuột ổ rò rỉ RAM (memory leaks).
Bốn Ánh Vàng Thần Thánh (Four Golden Signals) — Móng Cái Đài Quan Sát Cắm Dùi Bám (Observability Foundation)
Answer-first: Bốn Tín Hiệu Vàng lượm từ Kinh Thư SRE của Google là cái rổ số liệu đo đếm dẻ rách (minimum metrics) kịch sàn phải có đặng soi rọi bắt mạch bốc thuốc sống chết (health) của bất kỳ con ghẻ dịch vụ nào. Hễ xắn tay đầu tư đào sâu chọc lỗ chẩn bệnh mổ xẻ (profiling) chi tiết, thì đè cổ rà soát cho trót lọt 4 cái cột đình này cắm rễ trơn tuột và la làng hú hét chuẩn chỉ giùm tao.
| Mạch Tín Hiệu (Signal) | Thước Cặp (Metric) | Mỏ Nhặt Ở Go (Go Source) | Nút Kích Ngòi (Alert Condition) |
|---|---|---|---|
| Trễ Mức (Latency) | Nhịp lê lết p50/p95/p99 (request duration) | Biểu đồ cột (histogram) promhttp | Nhịp p99 > Hố chi tiêu lầy lội SLO budget |
| Xô Bồ (Traffic) | Lượng rác quăng dô mỗi giây (Requests per second) | Đồng hồ đếm (counter) promhttp | Rớt không phanh (Tín hiệu sập tiệm - outage signal) |
| Ăn Miểng (Errors) | Nhịp lỗi rác HTTP 5xx (error rate) | promhttp đính tem (label) status | Tràn mâm > 0.1% lưu lượng húp (traffic) |
| Tắc Tịt Bội Thực (Saturation) | %CPU, %RAM, số lượng goroutine | Ruột runtime.MemStats | Ăn ngập RAM > 80% hạn mức chuồng (container limit) |
Sa Bàn Chọc Ngoáy Mổ Xẻ pprof (The pprof Profiling Grid)
Answer-first: Đồ tể net/http/pprof vạch ngực phơi bày 6 lỗ cắm chẩn bệnh (profiling endpoints). Từng lổ chuyên trị vạch mặt một bọc bệnh (class of problem) riêng lẻ. Dở thói bấu víu (side-effect import _ "net/http/pprof") đặng vô luồn tay cài cắm hết sạch ba cái ngàm đón rước (handlers) trên chóp http.DefaultServeMux một cách tự động.
| Cửa Cắm (Endpoint) | Nghề Mổ Xẻ (Profile Type) | Tiền Ngu (Overhead) | Đụng Là Bắt (Diagnoses) |
|---|---|---|---|
/debug/pprof/heap | Đống Rác (Heap) — ngậm mồm (inuse) & khạc nhổ (allocs) | < 1% | Lủng ruột xì RAM (inuse_space), Nghẹn họng dọn rác GC (alloc_space) |
/debug/pprof/goroutine | Dấu vết cào cấu nguyên bầy (All goroutine stack traces) | < 0.1% | Ngập lụt xì goroutine — tụi nó kẹt dí chết trân (blocked indefinitely) |
/debug/pprof/profile?seconds=30 | Nhấp nháp nếm CPU (100Hz) | ~5–10% | Tắc cổ chai CPU — lòi mảng phễu code rực lửa (hot code paths) |
/debug/pprof/block | Bắt trọn khoảnh khắc kẹt ngõ (Goroutine block events) | ~2–5% | Nghẹn ống chan/ổ khóa (channel/mutex stalls) đẻ ra lê lết (latency) |
/debug/pprof/mutex | Đánh lộn giật ổ khóa (Contended mutex events) | ~2–5% | Sứt đầu mẻ trán giành giật khóa giữa bầy goroutines |
/debug/pprof/trace?seconds=5 | Bắt bóng chạy đua full trọn (Full execution trace) | ~10–15% | Lễ dọn rác GC, Màn bốc thuốc lịch chạy scheduler, Lê lết cọ cống HĐH (syscall) |
Lên Dàn Gác Đồ Tể pprof (pprof Server Setup)
package main
import (
"log"
"net/http"
_ "net/http/pprof" // Trót dại móc lốp (Side-effect import): rắp rắp cài cắm ba cái cửa /debug/pprof/*
)
func main() {
// Nhét ổ pprof ra riêng 1 xó port — CẤM CỬA không bao giờ lột truồng khoe ra ngoải (publicly)
go func() {
log.Println("Thằng chọc ngoáy pprof rình rập ở localhost:6060")
// Trói lổ rốn vô localhost chốt cứng ngắc chỉ đám lính trong nhà host hay phải mò luồn cổng (port-forward) mới sờ được
if err := http.ListenAndServe("localhost:6060", nil); err != nil {
log.Printf("Ổ chọc ngoáy pprof hắt hơi sổ mũi: %v", err)
}
}()
// Mỏ nhà chính ngự trị (Main application server)
http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
})
log.Fatal(http.ListenAndServe(":8080", nil))
}
[!CAUTION] Cấm cửa tuyệt đối đem khoe khoang pprof ra hớ hênh thiên hạ (publicly). Lão pprof hở sườn phơi bày 1 mớ ná thở lộn gan nhạy cảm: nguyên thớ xấp dấu vết xếp chồng (stack traces) (tên cúng cơm hàm, mả đường dẫn, mả địa chỉ RAM), sổ nam tào băm phay khai báo húp rác RAM (allocation patterns), và bộ mặt lõi song song chọc ngoáy sâu trong ruột (internal concurrency structure). Đóng cửa khép nách rúc mỏ vô bằng:
kubectl port-forward pod/my-pod 6060:6060(Bên xứ mảng Kubernetes)- Đào hầm VPN nội mác (Internal VPN) hoặc lô cốt cửa khẩu (bastion host)
- Lưới giăng ma thuật mTLS service mesh (authorization policy)
Vạch Mặt Xì Đáy Đống rác RAM (Memory Leak Diagnosis) — 5 Chưởng So Mâm (Heap Diff)
Answer-first: Trò xì RAM ở xứ Go thông thường trồi lòi phèo lúc: (1) bầy goroutines ngáp ruồi đơ cổ ứ hự ngậm chặt mấy cái dây bấu víu (references), (2) rổ lủng lẳng slices/maps phình to trương sình chẳng có điểm dừng, (3) mấy lổ chứa (caches) hốc tọng vào mà quên bà nó chính sách khạc nhổ móc họng nôn (eviction policies). Bùa ngải trị nhanh nhất là bế 2 cục rác băm heap (snapshots) ra gõ chẻ đôi soi vết — 1 chụp trước lúc cày cuốc, 1 bợ sau mẻ nhồi tải bạo bệnh (load period).
Từng Nhát Băm Phay (Step-by-Step Process)
# Nháy 1: Chộp tấm hình nền chốt bãi hốc rác (Capture baseline heap)
curl -sK -v -o baseline.pprof http://localhost:6060/debug/pprof/heap
echo "Chốt hòm hình nền: $(date)"
# Nháy 2: Lôi ra nhồi quất đòn (load) hay rung đùi ngó 5–15 phút dưới mẻ pháo traffic trần tục production
# Nháy 3: Bắn chụp đống bã vãnh dơ dáy ngập mồm (Capture peak heap snapshot)
curl -sK -v -o peak.pprof http://localhost:6060/debug/pprof/heap
echo "Bắt đỉnh thét gào: $(date)"
# Nháy 4: Phay đôi 2 đống rác (Diff profiles) — lòi tòi phòi ĐÚNG NHÕN chỗ phình (cột khói lọt rò rỉ xì RAM - leak signal)
go tool pprof -base baseline.pprof peak.pprof
# Nháy 5: Rúc vô mai rùa hầm lò gõ (In interactive shell)
(pprof) top 20 # 20 đứa đầu sỏ hốc rác ăn tạp (allocation increase)
(pprof) list SuspectFunc # Xẻ ruột soi lòi tòi phòi từng dòng vắt vếu nuốt RAM của 1 hàm
(pprof) web # Lôi đầu ném lên mạng nhện (browser) coi tháp nhang rực cháy (flame graph - ép xài graphviz)
Cuốn Bí Kíp Cào Câu Lệnh pprof Dắt Lưng (Common Commands Reference)
# Mổ xẻ CPU (CPU profile): nhấp ngụm gặm nhấm 30 giây (móc xỉa tốn 5–10% tiền ngu CPU (overhead) lúc nhai)
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
# Xẻ thịt mỡ Heap (Heap profile) — Dán mắt zô cục máu tươi (live objects) (Bắt tại trận xì RAM - memory leak detection)
go tool pprof -inuse_space http://localhost:6060/debug/pprof/heap
# Xẻ thịt mỡ Heap — Rọi đèn zô BÃI rác tổng rác xả ra (total allocations) (Soi bóng đè áp lực dọn bồn cầu GC pressure)
go tool pprof -alloc_space http://localhost:6060/debug/pprof/heap
# Đổ bô (dump) nguyên 1 lốc goroutine phơi thây xương xẩu (full stack traces) — bóp vòi vắt qua grep
curl http://localhost:6060/debug/pprof/goroutine?debug=2 -o goroutines.txt
grep -A 20 "goroutine [0-9]* \[chan receive" goroutines.txt # Dò tìm mấy đứa goroutines ngậm mồm mắc cạn (blocked)
# Chơi múa xập xình trên nền web với tháp nhang rực cháy (flame graph) (móc browser tới ổ :8090)
go tool pprof -http=:8090 http://localhost:6060/debug/pprof/heap
Oánh Lộn inuse_space vs alloc_space — Chọn Bùa Nào Quất?
Answer-first: Lưỡi dao inuse_space phanh phui khúc lòng phèo đang ngậm chặt (currently held - live objects) — xài bùa này đi săn mẻ rò rỉ RAM lủng lổ (memory leaks). Lưỡi cưa alloc_space phơi trần ngồn ngộn cái đống thây ma rác đái tọng nhét từ lúc bú tí mẹ (tính sất mớ tàn dư đã bị xúc đổ bô bởi GC) — xài búa này đi bắt giò mấy mảng code lầy lội đẻ rác liên tục nắc cổ họng nhồi nhét ông hót rác GC (GC pressure).
Bàn Chớp Xử Án (Decision Guide)
| Hiện Tượng Trào Đờm (Symptom) | Chiêu Thức Rạch Mổ (Profile Mode) | Hố Chó Gì Đây (Why) |
|---|---|---|
| Lũ RAM phình lòi tòi phòi vĩnh viễn, chẳng chịu xẹp (grows continuously) | Phay đôi mâm inuse_space heap diff | Lũ máu tươi ứ đọng lầy lội (Live object accumulation) |
| CPU thét gào nổ tung óc nhưng ngáo chẳng rành nguyên cớ | Rạch sườn CPU profile (30s) | Tóm cổ mảng phễu ngập hành (hot code paths) |
| Hót rác GC chết đứng bóng > 100ms (GC pauses) | Cạo alloc_space | Túm mỏ mấy vòi nước khạc rác chớp nhoáng (high-frequency allocation paths) |
| Đầu bò goroutine sinh sôi nảy nở đẻ trứng chẳng nín (grows without bound) | Múc đổ bô goroutine dump (?debug=2) | Lủng máng xì goroutines — nghẹn họng mấy mương nước (blocked channels) |
| Lê lết bò trườn (High latency) trớ trêu thay CPU lại héo hon (low CPU) | Rạch sườn Block profile | Cự cãi nhốt nhét chen ngang mương/khóa (Channel/mutex contention stalls) |
Bươi Rác GODEBUG GC Trace — Phanh Phui Ngó Bộ Lòng (Reading the Output)
Answer-first: Đẩy cọc GODEBUG=gctrace=1 nhổ phẹt ra tràng giang đại hải sổ nam tào dọn rác GC vô họng stderr — độ chà bá hố rác heap, nhịp nín thở chết lặng (pause durations), và miếng xơi đớp % CPU. Chiêu hèn kế bẩn bọc thép nhanh nhất nặn nhọt họng ách tắc GC (GC pressure) mà khỏi phải mâm cỗ ậm ờ rước pprof.
export GODEBUG=gctrace=1
./my-service 2>&1 | grep "^gc"
# Mẻ bã rác phọt ra mồm (Sample output):
# gc 1 @0.005s 3%: 0.012+1.5+0.045 ms clock, 0.096+1.5/1.2/0+0.36 ms cpu, 4->4->2 MB, 5 MB goal, 8 P
Xé Mành Mành Mớ Bã Nhầy (Parsing the Output)
gc 1 = Rặn ỉa hốt rác (GC cycle) bận số 1
@0.005s = 5ms sau nhịp đẻ nổ tung quá trình (process start)
3% = Cắn xén 3% máu CPU giam mình hốt rác (hét bậy nín họng hễ vọt > 5%)
0.012+1.5+0.045 ms clock:
0.012 ms = Nín thở trần gian (stop-the-world) đóng đinh quét chóp termination pause
1.5 ms = Lặn hụp bơi lội đánh dấu quét tước (concurrent mark and sweep phase)
0.045 ms = Nín thở trần gian chốt chặn kết tủa (mark termination pause)
4->4->2 MB:
4 MB = Hố phân heap chà bá lúc hếch mỏ rặn ỉa GC
4 MB = Hố phân heap lúc vẫy cờ chốt quét đánh dấu (end of marking)
2 MB = Đống máu mủ thịt lòi sành rành bấu víu bám trụ (live heap) còn thoi thóp sau mẻ gạt xúc
5 MB goal = Đích nhắm ngập hố rác tọng vô trước khi bóp còi bận ỉa GC lết kế tiếp (Bấu víu tỉ lệ GOGC)
8 P = Lốc tay sai vi xử lý goroutine gặm xương (GOMAXPROCS)
[!WARNING] Nhồi máu GC đớp %CPU > 5% là tiếng gõ cửa tử thần đè đầu vắt chân lên cổ mà sửa ngay (optimize). Mấy đơn thuốc dân gian (Common remediations): bóp mồm bóp miệng giảm bớt thói tọng phân rác khạc nhổ allocations (chơi đồ tái chế xài chạc
sync.Pool), chọc vọt cái trầnGOGC(chuẩn gốc 100 — bồi GC xả ỉa hễ rác rác heap nở gấp đôi; nhích phình mỏ lên 200 để ép lòi trĩ nín nhịn xả GC thưa ra tí), hoặc móc cài ngàmGOMEMLIMIT(từ Go 1.19+) lấy búa gõ trần chặn đứng ỉa non GC trước mẻ ngợp ngộp OOM chết chùm.
Bắt Mạch Xì Bọng Đái Goroutine (Goroutine Leak Detection)
Answer-first: Một cục mụn bọc rò rỉ goroutine phọt lòi lúc bầy chó goroutines kẹt xe chết trân vĩnh viễn không lối thoát (block indefinitely) — ngáp ruồi chầu chực cắm ở 1 cái mương (channel) không bao giờ có hàng thảy vô, khất thực 1 ổ khóa (lock) không bao giờ được phóng sinh, hoặc trơ mỏ bấu víu vô 1 cái tròng (context) chẳng mống nào thèm bóp cò giật sập hủy (cancelled). Đàn goroutine sinh sôi nảy nở ngập ngụa (grows monotonically) bồi thêm nguyên đống RAM thịt mỡ tọng sưng phồng tịnh tiến theo cục nợ stack mốc meo của lũ trôi sông lạc chợ lủng đái đó (leaked goroutines).
package observability
import (
"fmt"
"runtime"
"time"
)
// Mõ Làng GoroutineLeakDetector hét ra lửa khi ruồi nhặng goroutine bủa vây vượt chóp mức chịu đựng (threshold)
type GoroutineLeakDetector struct {
baseline int
threshold int
}
func NewGoroutineLeakDetector(threshold int) *GoroutineLeakDetector {
return &GoroutineLeakDetector{
baseline: runtime.NumGoroutine(),
threshold: threshold,
}
}
func (g *GoroutineLeakDetector) Check() bool {
current := runtime.NumGoroutine()
if current > g.baseline+g.threshold {
fmt.Printf("TRÁT ĐÒI MẠNG (ALERT): ruồi_goroutines=%d (rốn_baseline=%d, chóp_threshold=+%d) — xì lủng bọng đái rồi mày!\n",
current, g.baseline, g.threshold)
return true
}
return false
}
// Loa Phường RuntimeMetricsExporter nhai nhải hót tràng giang rải số liệu Go runtime metrics theo nhịp
type RuntimeMetricsExporter struct {
interval time.Duration
}
func (e *RuntimeMetricsExporter) Start() {
go func() {
ticker := time.NewTicker(e.interval)
defer ticker.Stop()
for range ticker.C {
var ms runtime.MemStats
runtime.ReadMemStats(&ms)
fmt.Printf("[chuồng_runtime] ruồi_goroutines=%d rác_ngậm_heap_inuse=%dMiB rác_tổng_heap_alloc=%dMiB hót_rác_gc_total_pause=%dms số_bận_gc_cycles=%d\n",
runtime.NumGoroutine(),
ms.HeapInuse/1024/1024,
ms.HeapAlloc/1024/1024,
ms.PauseTotalNs/1_000_000,
ms.NumGC,
)
}
}()
}
Mấy trò lèo lá rò rỉ xì ruột goroutine bá dơ ngập chốn Go:
// ❌ SỤP HỐ XÌ rác (LEAK): chó goroutine nghẹn mõm ngay cái mương channel mà chẳng có con ma nào thèm rúc hút (nobody reads)
func leakyHandler(w http.ResponseWriter, r *http.Request) {
ch := make(chan Result) // Mương cạn chẳng bọc đệm (Unbuffered channel)
go func() {
result := expensiveWork()
ch <- result // Chết trân hóa thạch (Blocks forever) hễ thằng gọi phủi chóp vọt mịa nó mất từ đời tám hoảnh (returns early)!
}()
select {
case res := <-ch:
w.Write(res.data)
case <-time.After(1 * time.Second):
http.Error(w, "đứt bóng (timeout)", 504) // Phủi chóp dong (Returns)! Nhưng kẻ goroutine vẫn nằm sấp mặt chết dí ở ch<-
}
}
// ✅ THỐC THUỐC TIÊN (FIXED): xài bùa giật sập rút còi context (context cancellation) đặng mở ngàm lôi đầu goroutine ra
func fixedHandler(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), time.Second)
defer cancel() // Nhai nhải giật sập hủy (Always cancel) — kể cả khi nhậu ngọt mượt mà
ch := make(chan Result, 1) // Mương bọc đệm (Buffered) — goroutine rống họng quăng ỉa vô tư trót lọt
go func() {
select {
case ch <- expensiveWork():
case <-ctx.Done(): // Phủi chóp vọt mẹ lẹ (Exit) nếu sợi dây context bị cắt đứt
}
}()
select {
case res := <-ch:
w.Write(res.data)
case <-ctx.Done():
http.Error(w, "đứt bóng (timeout)", 504)
}
}
Sa Bàn Phơi Bày Nhòm Ngó Production (Production Observability Stack)
package observability
import (
"fmt"
"net/http"
_ "net/http/pprof" // Rải rác móc lốp cài cắm /debug/pprof/* handlers
"time"
)
// StartObservabilityStack nổi lửa nướng cựa trọn mâm ốp la ngó ngoáy (observability components)
func StartObservabilityStack(pprofPort int, leakThreshold int) {
// 1. Quầy hàng pprof server (mở cửa bít bùng luồn chui nội mạng - internal only)
go func() {
addr := fmt.Sprintf("localhost:%d", pprofPort)
fmt.Printf("[tai_mắt_observability] Lò mổ pprof chễm chệ chực hờ ở http://%s/debug/pprof/\n", addr)
http.ListenAndServe(addr, nil)
}()
// 2. Loa phường khạc số liệu Runtime (cứ mỗi 15 giây nhè đờm 1 phát)
exporter := &RuntimeMetricsExporter{interval: 15 * time.Second}
exporter.Start()
// 3. Mõ làng hửi rò rỉ ngó goroutine (đi tuần gõ mỏ mỗi 30s)
detector := NewGoroutineLeakDetector(leakThreshold)
go func() {
for range time.Tick(30 * time.Second) {
detector.Check()
}
}()
}
Mổ Xẻ Chuyện Trà Dư Tửu Hậu (Case Study): Rò Rỉ Mủ RAM Quậy Banh Cái Túi Đựng Chung (Shared Buffer) — Tan Nát Đời Trai Production (Production Incident)
🔥 [Thảm Kịch Bãi Chiến Trường Production]: Bầy Đàn Go OOM Sập Hầm — Phình To 2 GB/giờ (Go Service OOM — 2 GB/hour Growth) Bệnh chứng (Symptom): Cục dịch vụ phình nẩy đẻ mỡ 2 GB/giờ. Ăn đòn OOM chém đầu kết liễu đời chó sau 8 tiếng lay lắt. CPU hiền khô nhởn nhơ (normal). chẳng lòi tòi phòi ba cái đường dây bốc lửa rõ ràng sất (No obvious hot path). Đào mả soi mói (Investigation):
go tool pprof -base baseline.pprof peak.pprof (pprof) top 5 # → văng ra strings.(*Builder).WriteString: +1.8 GB nứt rạn rác bành trướngRễ Bệnh Đực Dựa (Root Cause): Cớ sự tại một thằng bảo kê HTTP middleware nhồi nhét ói đái nùi đường dẫn URL (request URL paths) lốc vô một vũng lầy lội
strings.Builderbú chung bị chộp dính phốt trong một thòng lọng closure — thằng bỏ búa (variable) đó bị trói đính chặt vào cái kiếp lai sinh của ông cụ server (server lifetime), chứ chẳng phải thọ mạng sống lay lắt của bọt bèo request.// ❌ Phốt vỡ họng bốc mả (Bug): thằng đực rựa buf bị tóm dính ngay lúc lôi chóp server ra múa khởi tạo (server init), cấm cửa không bao giờ vác nùi cọ rửa dọn nát (never reset) var buf strings.Builder mux.Handle("/api/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { buf.WriteString(r.URL.Path) // Phình mỡ vô tận! (Grows forever!) // ... })) // ✅ Bốc Thuốc (Fix): Rạch vỏ tách biến xài ké địa phương (local variable) ném vòng thọ mệnh bóp móp méo vào từng chóp request mux.Handle("/api/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var buf strings.Builder // Khạc đái nặn đẻ bóp riêng từng mẻ request, GC tóm đuôi xúc dọn rửa láng o ngay hễ hàm handler sổ lồng vọt (returns) buf.WriteString(r.URL.Path) // ... }))Đóng hòm êm xuôi (Resolution): Bùa chẻ đống rác so mâm (Heap diff) soi tận giường bắt tận mặt cái hàm yêu tinh gây họa móp mép lỏn lẻn < 10 phút múa may. Xức thuốc chữa nhõn tráo 1 dòng cắt vòi thọ mệnh scope (single-line scope change). Nhọt rò rỉ RAM lủng lổ chém đầu tịt nín bặt (eliminated).
Bọc Cổ Đóng Hòm Cuốn Bí Kíp (Series Summary) — Khóa Luyện Đan System Design (Golang)
Chú em vừa nuốt trọn 10 mẻ võ vẽ của cuộn bí kíp võ lâm. Dưới đây là bãi sa bàn đống võ vẽ (knowledge map) chú mày đã tậu:
| Bài | Mâm Chuyện (Topic) | Nút Thắt Gút Lõi (Core Concept) |
|---|---|---|
| 1 | Tư Duy Gò Hàng (System Design Thinking) | CAP/PACELC, bùa đánh đổi xào chẻ (trade-off framework), Gò Sạch Thơm Tho (Clean Architecture) |
| 2 | Quật Cân Tải (Load Balancing) | L4 vs L7, phọt đường tắt DSR, lấp lỗ bóp cổ Token Bucket (rate limiting) |
| 3 | Mẹo Ăn Dặm Tọng Rác (Caching) | Ép 1 chóp Singleflight + lừa gạt XFetch + Chôn Lầu Tầng (Tiered Cache) |
| 4 | Thổi Phình Bóng Đái CSDL (Database Scaling) | B-Tree vs LSM, phay băm chẻ thịt (sharding), hố tọng mâm database/sql pool |
| 5 | Thổi Còi Múa Rối Sự Kiện (Event-Driven) | Kafka không lót tay (zero-copy), Lô cốt cu li Worker Pool, Bắn trúng phóc 1 nhát (Exactly-Once) |
| 6 | Ổ Khóa Cùm Giăng Xé (Distributed Locks) | Vắt óc ná thở toán Redlock, vỗ mâm etcd Raft, xẻ đôi sọ não (split-brain) |
| 7 | Nặn API Chặn Đúp Cản Pháo (Idempotent APIs) | Bảo kê nhồi SetNX middleware, bùa cản Stripe |
| 8 | Nhùi Nhét Giao Dịch Loạn Cào Cào (Distributed Transactions) | Dàn nhạc Temporal Saga, Lỗ tọng Outbox, nhồi sọ Debezium |
| 9 | Băm Nhất Quán Vun Đầy (Consistent Hashing) | Hạt mìn ảo (Virtual nodes), vòng thép CRC32 ring, múa GetN |
| 10 | Tai Mắt Rạch Soi (Observability) | pprof, chẻ rác heap diff, bới GODEBUG, lụt lội goroutine leaks |
| 11 | Lót Giáp API An Toàn (API Security) | Boong ke giáp gai (Layered defense), lật mặt nạ XFF spoofing, trượt ván Redis Lua sliding window |
| 12 | Hò Hét Thông Tin (Communication) | Đúc phôi thép ruột Protobuf, phi lướt HTTP/3 QUIC, vắt óc bùng nổ GraphQL, ConnectRPC |
🔗 Bay Sang Bài Tới: Phần 11: Đóng Giáp Security & Bóp Cổ Nhồi Nhét API (API Rate Limiting) — Thùng Lủng Lỗ Token Bucket, Bình Lủng Đáy Leaky Bucket & Ma Thuật Redis Lua
Hỏi Nhanh Đáp Gọn (FAQ)
Rình Rập Chọc Bắt Ổ Rò Rỉ RAM (memory leaks) Ở Go Ra Sao Cưng?
Phệt trọn 5 đường múa: (1) bợ chộp tấm hình chụp đống rác gốc bằng curl .../heap -o baseline.pprof, (2) nện tải vắt óc cày bừa đụ (load test) rỉ rả 10–30 phút, (3) lụm tấm đỉnh thét gào peak heap, (4) chọt đôi gõ go tool pprof -base baseline.pprof peak.pprof, (5) múc top 20 hốt vạch mặt lòi họng mấy hàm yêu tinh ngậm hút băm nát hốc tọng phình bành bướng nhất. Còn chọc đục lòi phọt goroutine leak thì xài búa: curl .../goroutine?debug=2 gòi bóp chai grep xả láng kiếm cặn rác chan receive ngộp chìm trong mớ bã hót ra.
Trình Xiếc Khỉ Xài Mỏ Hàn go tool pprof Như Thế chẳng Nào Nhỉ?
# Sắn mỡ CPU (mót cắn bậy 5–10% tiền máu (overhead) lúc sục xạo ngửi rác):
go tool pprof http://localhost:6060/debug/pprof/profile?seconds=30
# Soi ruột Heap (cạp nhè nhẹ < 1% tiền ngu):
go tool pprof -inuse_space http://localhost:6060/debug/pprof/heap
# Phơi màn lưới nhện tháp nhang rực cháy flame graph (web UI):
go tool pprof -http=:8090 http://localhost:6060/debug/pprof/heap
# Rúc hầm lò múa bàn phím (Interactive commands): top / list <func> / web / svg
Cái Vẹo Gì Chẻ Đôi Thằng inuse_space Với Thằng alloc_space Vậy?
inuse_space = nùi thịt mỡ đang ngậm rúc chặt (currently held - bầy bâu xâu máu tươi). Nhè nó ra quất để soi mụn lủng xì RAM (memory leaks) — hễ vạch thấy nó phình nẩy nắn chà bá không ngót theo thời gian, là đích thị có mẻ rác lầy lội ứ hự tích tụ đang phọt lòi. alloc_space = rổ xác ướp tổng đống bã mỡ rác bị nhồi nhét cào xé lôi lên từ lúc phôi thai chạy nổ quá trình, gom lượm bao thầu cả mớ rác ruồi đã bị hót rửa bằng GC. Xách đi chọc mảng vạch bã code lầy lội móc họng ói đái rác quá trớn (hot allocation paths) thọt lét ép chú GC lôi đầu ra rửa dọn (frequent GC cycles). Bơi hố ngửi rác rò rỉ xì RAM (memory leak) → inuse_space. Xì phao tháo van ức chế bóp cổ cụ GC (GC pressure) → alloc_space.