Documentation
¶
Overview ¶
Package lb chọn backend cho mỗi request (phase 6): round robin, least connections, P2C+EWMA, consistent hashing; kèm hai cơ chế sức khoẻ song song — active health check (goroutine nền) và passive outlier ejection (đếm lỗi trên traffic thật). Chỉ dùng net + httpx; không net/http.
Ranh giới với proxy: proxy gọi đúng hai hàm — Pick(key) trước khi lấy connection, Done(b, latency, failed) sau khi exchange xong (D2). Inflight đếm theo REQUEST, không theo connection trong pool (P5-3).
Index ¶
- func Hash32(s string) uint32
- type Backend
- type BackendStats
- type Balancer
- func (bl *Balancer) Backends() []*Backend
- func (bl *Balancer) Close()
- func (bl *Balancer) Done(b *Backend, latency time.Duration, failed bool)
- func (bl *Balancer) Pick(key string) *Backend
- func (bl *Balancer) PickExcept(key string, ex *Backend) *Backend
- func (bl *Balancer) Start()
- func (bl *Balancer) Stats() Stats
- type Config
- type HealthConfig
- type OutlierConfig
- type Picker
- type Stats
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Hash32 ¶
Hash32: FNV-1a 64 + bước trộn cuối của MurmurHash3 (fmix64), lấy 32 bit thấp.
Bản đầu chỉ FNV-1a gập 64→32: FNV không có avalanche, các vnode "addr#0", "addr#1", … của CÙNG một backend rơi gần nhau trên ring ⇒ 150 vnode vẫn lệch tải 3.57x, và 1000 vnode vẫn 2.85x (đo ở turn 1, xem phase6-log §1). Vnode chỉ làm mịn khi hash rải đều; fmix64 đưa về 1.17x. Export để test tính `hash % N` đối chứng.
Types ¶
type Backend ¶
type Backend struct {
Addr string
// contains filtered or unexported fields
}
Backend là một upstream. Mọi trường đếm là atomic vì Pick/Done chạy từ nhiều goroutine client cùng lúc; health checker ghi healthy từ goroutine riêng.
type BackendStats ¶
type BackendStats struct {
Addr string
Picks int64
Inflight int64
Fails int64
Ejections int64
EWMA time.Duration // điểm EWMA hiện tại (đã decay tới lúc chụp)
Healthy bool // active
Ejected bool // passive
State string // breaker: closed | open | half-open (phase 7)
Probes int64 // số request thử ở half-open
Reopens int64 // half-open thử hỏng ⇒ open lại
}
BackendStats: ảnh chụp một backend.
type Balancer ¶
type Balancer struct {
// contains filtered or unexported fields
}
Balancer = danh sách backend + picker + sức khoẻ. Proxy chỉ gọi Pick và Done.
func (*Balancer) Close ¶
func (bl *Balancer) Close()
Close dừng health check và chờ goroutine thoát.
func (*Balancer) Done ¶
Done: request trên b đã xong (exchange trả về — client đã nhận response VÀ connection đã put/discard trong defer của exchange; D2 ghi "trước put" là sai, chênh vài µs, xem diary phase 6 câu 2). latency nuôi EWMA; failed nuôi outlier.
func (*Balancer) Pick ¶
Pick chọn backend cho request có khoá key (chỉ chash dùng) và tăng inflight (D2: đếm theo request, từ ĐÂY). nil ⇒ không còn backend nào dùng được ⇒ 503.
func (*Balancer) PickExcept ¶
PickExcept: như Pick nhưng không bao giờ trả ex (P7-1, trả 2026-10-02). Proxy dùng cho lượt chọn lại D9 sau khi dial ex lỗi — bản cũ gọi Pick ⇒ least-conn hoà inflight / rr một backend chọn lại CHÍNH ex ⇒ 2× DialTimeout rồi 502.
type Config ¶
type Config struct {
// Algo: "rr" | "leastconn" | "p2c" | "chash".
Algo string
// Tau: hằng thời gian EWMA của p2c. Mặc định 1 s. Quá dài ⇒ phản ứng chậm (G3).
Tau time.Duration
// HashHeader: header làm khoá cho chash; rỗng ⇒ proxy dùng IP client sau
// ranh giới tin cậy. Header thiếu ⇒ cũng rơi về IP.
HashHeader string
// VNodes: điểm ảo / backend cho chash. Mặc định 150.
VNodes int
Health HealthConfig
Outlier OutlierConfig
Logf func(format string, args ...any)
}
Config của Balancer. Zero value: rr, tau 1 s, 150 vnode, health + outlier bật.
type HealthConfig ¶
type HealthConfig struct {
Disabled bool
Interval time.Duration
Timeout time.Duration
// Path: nếu khác rỗng, sau khi dial gửi `GET Path` raw và đòi status < 400.
// Rỗng = chỉ cần TCP connect thành công.
Path string
Fall int // lỗi liên tiếp ⇒ unhealthy (nginx max_fails)
Rise int // tốt liên tiếp ⇒ healthy
// Dial (P8-3): thay net.DialTimeout — proxy đặt khi upstream nói TLS để
// probe bắt tay TLS trước khi gửi GET Path. nil = TCP trần. lb không biết
// TLS: cert/SNI là việc của proxy, lb chỉ cần một net.Conn đã sẵn sàng.
Dial func(addr string, timeout time.Duration) (net.Conn, error)
}
HealthConfig: active health check (D6). Zero value = bật, Interval 2 s, Timeout 1 s, chỉ dial TCP (Path rỗng), Fall 3, Rise 2.
type OutlierConfig ¶
type OutlierConfig struct {
Disabled bool
Consecutive int
BaseEject time.Duration
MaxEject time.Duration
MaxEjectPercent int
}
OutlierConfig: passive outlier ejection (D7, Envoy consecutive_5xx). Zero value = bật, 5 lỗi liên tiếp, eject 30 s × 2^(n-1), trần 5 phút, không eject quá 50 % backend.