shard

package
v0.6.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 10, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

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

func Jump(key uint64, buckets int) int

Jump 是 Google 的 Jump Consistent Hash:把 key 映射到 [0, buckets) 的一个桶,几乎无内存、 无需哈希环,且桶数从 n 变到 n+1 时,只有约 1/(n+1) 的 key 会迁移(最小化再分布)。 适合桶(分片/副本)按 0..n-1 连续编号、且只在尾部增减的场景。buckets<=0 返回 0。

局限:桶必须是连续整数编号,不能任意增删中间桶(那种场景用一致性哈希环或 Rendezvous)。

func PathHeadKey

func PathHeadKey(r *http.Request) string

PathHeadKey 从请求路径取第一段作为分片 key(与 media.Hub 的 /{key}/… 路由对齐)。

Types

type Member

type Member interface {
	ID() string
	Weight() int
	Addr() string
}

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

func WithVirtualFactor(n uint32) Option

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, 归属他机的反向代理过去。并发安全。

func NewRouter

func NewRouter(s *Sharder, keyFn func(*http.Request) string, local http.Handler) *Router

NewRouter 创建分片路由。keyFn 从请求提取分片 key(如 PathHeadKey);local 服务归属本机的 key。

func (*Router) ServeHTTP

func (rt *Router) ServeHTTP(w http.ResponseWriter, r *http.Request)

type Sharder

type Sharder struct {
	// contains filtered or unexported fields
}

Sharder 维护成员集合并做一致性哈希归属。并发安全。零值不可用,用 New 构造。

func New

func New(self string, members []Member, opts ...Option) *Sharder

New 创建 Sharder。self 是本实例 ID(须等于本实例在 members 里的 ID);members 是初始成员集。

func (*Sharder) IsLocal

func (s *Sharder) IsLocal(key string) bool

IsLocal 判断 key 是否归属本实例。成员集为空(单机部署 / 尚未发现其他实例)时视为本地。

func (*Sharder) Members

func (s *Sharder) Members() []Member

Members 返回当前成员集合(副本)。

func (*Sharder) Owner

func (s *Sharder) Owner(key string) (Member, bool)

Owner 返回 key 的归属实例。成员集为空时返回 (nil, false)。

func (*Sharder) Self

func (s *Sharder) Self() string

Self 返回本实例 ID。

func (*Sharder) SetMembers

func (s *Sharder) SetMembers(members []Member)

SetMembers 用新的成员集合重建哈希环(服务发现变更时调用)。并发安全。

type StaticMember

type StaticMember struct {
	NodeID     string
	NodeWeight int
	NodeAddr   string
}

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

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL