Documentation
¶
Overview ¶
Package shard 给「有状态服务」提供多副本分片路由的薄机制:用一致性哈希把每个 key (streamKey / roomID / userID 等)确定性地归属到某一个实例,请求落到非归属实例时 反向代理转发给归属实例。从而让 media.Hub、webrtc/sfu 房间、gameloop 房间、presence 这些**进程内单实例**的有状态服务能水平扩多副本——服务本身不用改成分布式,分片层坐在前面。
两块能力:
- Sharder:成员集合上的一致性哈希归属(基于 pkg/loadbalance.ConsistentHash), Owner(key) 给出归属实例、IsLocal(key) 判断是否本机。成员集合可随服务发现动态更新 (SetMembers),归属在成员增减时最小化迁移。
- Router:http.Handler,按 key 把非本地请求反代给归属实例(WebSocket 也支持, httputil.ReverseProxy 处理 Upgrade)。本地 key 交给本地 handler。
边界(机制而非策略):成员从哪来(服务发现)、key 怎么从请求里取、权重怎么定,都是 policy。典型接法:
self := shard.StaticMember{NodeID: hostname, NodeAddr: "http://" + podIP + ":8090"}
sh := shard.New(self.ID(), self)
// 用 pkg/service/discover 监听实例变化,变了就 sh.SetMembers(all...)
hub := media.NewHub(func(k string) *hlsmux.Bridge { ... })
mux.Handle("/live/", http.StripPrefix("/live", shard.NewRouter(sh, shard.PathHeadKey, hub)))
// 播 /live/roomA/index.m3u8 → 若 roomA 不归本机,自动反代给归属实例
一致性说明:成员集合在各实例间靠服务发现最终一致,churn 期间可能短暂不一致(两台都认为 自己不是 owner)。Router 用一个"已代理"标记头防止无限转发:带标记又仍非本地时就地服务, 宁可短暂错分也不打转。要强一致的归属请在其上叠加租约(pkg/dlock)。
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Jump ¶ added in v0.3.0
Jump 是 Google 的 Jump Consistent Hash:把 key 映射到 [0, buckets) 的一个桶,几乎无内存、 无需哈希环,且桶数从 n 变到 n+1 时,只有约 1/(n+1) 的 key 会迁移(最小化再分布)。 适合桶(分片/副本)按 0..n-1 连续编号、且只在尾部增减的场景。buckets<=0 返回 0。
局限:桶必须是连续整数编号,不能任意增删中间桶(那种场景用一致性哈希环或 Rendezvous)。
func PathHeadKey ¶
PathHeadKey 从请求路径取第一段作为分片 key(与 media.Hub 的 /{key}/… 路由对齐)。
Types ¶
type Member ¶
Member 是分片环上的一个实例。ID 要稳定(用作哈希与去重);Addr 是反代非本地请求的 基地址(如 "http://10.0.0.3:8090" 或 "10.0.0.3:8090",无 scheme 时按 http 处理)。
type Option ¶
type Option func(*Sharder)
Option 配置 Sharder。
func WithVirtualFactor ¶
WithVirtualFactor 设置每个实例的虚拟节点数(越大分布越均匀,默认 100)。
type Rendezvous ¶ added in v0.3.0
type Rendezvous struct {
// contains filtered or unexported fields
}
Rendezvous 是 Rendezvous(HRW,Highest Random Weight)哈希:对每个 key,选出使 hash(member, key) 加权得分最高的成员。相比一致性哈希环,它无需虚拟节点、实现更小, 天然支持权重,且增删任一成员只影响原属于/将属于该成员的 key(其余不动)。 适合成员可任意增删(非连续编号)、需加权、且成员数不特别大的场景(每次 Pick 是 O(成员数))。 并发安全。零值不可用,用 NewRendezvous 构造。
func NewRendezvous ¶ added in v0.3.0
func NewRendezvous(members ...Member) *Rendezvous
NewRendezvous 创建 HRW 选择器。
func (*Rendezvous) Members ¶ added in v0.3.0
func (r *Rendezvous) Members() []Member
Members 返回当前成员快照。
func (*Rendezvous) Pick ¶ added in v0.3.0
func (r *Rendezvous) Pick(key string) (Member, bool)
Pick 返回 key 对应得分最高的成员。无成员时返回 nil + false。
func (*Rendezvous) PickN ¶ added in v0.3.0
func (r *Rendezvous) PickN(key string, n int) []Member
PickN 返回 key 得分最高的前 n 个成员(按得分降序;不足则返回全部)。 用于副本放置:主 + 若干备。
func (*Rendezvous) Update ¶ added in v0.3.0
func (r *Rendezvous) Update(members []Member)
Update 替换成员列表。
type Router ¶
type Router struct {
// contains filtered or unexported fields
}
Router 是分片反代 http.Handler:按 keyFn 取出分片 key,归属本机的交给 local, 归属他机的反向代理过去。并发安全。
type Sharder ¶
type Sharder struct {
// contains filtered or unexported fields
}
Sharder 维护成员集合并做一致性哈希归属。并发安全。零值不可用,用 New 构造。
func (*Sharder) SetMembers ¶
SetMembers 用新的成员集合重建哈希环(服务发现变更时调用)。并发安全。
type StaticMember ¶
StaticMember 是 Member 的简单实现。Weight<=0 视为 1。
func (StaticMember) Addr ¶
func (m StaticMember) Addr() string
func (StaticMember) ID ¶
func (m StaticMember) ID() string
func (StaticMember) Weight ¶
func (m StaticMember) Weight() int