VIP 有三个节点 普通的有 normal 有两个节点,如何注册,当客户端收到 VIP 用户请求时,就会根据分组信息将请求路由到 VIP 节点,实现差异化服务。如何实现?
把 VIP 和普通实例注册到两套独立的 etcd key,相当于两个独立服务发现集合。
VIP 节点(3 台机器,配置相同)
# user-rpc-vip.yaml
Name: user.rpc
ListenOn: 0.0.0.0:8080
Etcd:
Hosts:
- 127.0.0.1:2379
Key: user.rpc/vip # VIP分组key
Normal 节点(2 台机器,配置相同)
# user-rpc-normal.yaml
Name: user.rpc
ListenOn: 0.0.0.0:8080
Etcd:
Hosts:
- 127.0.0.1:2379
Key: user.rpc/normal # 普通分组key
使用如下:
// 客户端配置
type Config struct {
UserVipRpc zrpc.RpcClientConf
UserNormalRpc zrpc.RpcClientConf
}
// 初始化两个client
vipClient := zrpc.MustNewClient(c.UserVipRpc)
normalClient := zrpc.MustNewClient(c.UserNormalRpc)
// 业务逻辑:根据用户身份选择client
if user.IsVIP {
resp, err := vipClient.UserService.GetUser(ctx, &req)
} else {
resp, err := normalClient.UserService.GetUser(ctx, &req)
}
CAP
C Consistency 一致性:同一时刻,所有节点读到的数据完全一样(强一致性)。A Availability 可用性:任何客户端请求,都能收到非失败的响应(服务可用,不超时、不拒绝)。P Partition tolerance 分区容错:网络发生分区(节点之间网络断了、丢包),整个系统仍然可以继续工作。
在没有网络分区(P 不存在)的理想单机环境下,可以同时满足 C+A;但分布式场景下,一定会存在网络分区,C 和 A 无法同时满足。
分布式系统,网络分区是客观一定会发生的(网线断、交换机故障、跨机房网络抖动),你无法规避网络分区
CP:牺牲 A,保证 C+P。网络分区发生时,为了保证所有节点数据一致,系统拒绝写入 / 阻塞请求,不再对外提供服务。 例子:Etcd、ZooKeeper(go-zero 用的 etcd 就是 CP 系统)。网络分区,多数派不可达:拒绝写请求,保证数据一致,牺牲可用性。
我们公司选择etcd主要是因为业务体量相对较小,集群规模不大,etcd 虽然是CP模式,但在我们的使用场景下也基本够用。不过我也在推动团队考虑迁移到Nacos的AP模式,以获得更好的可用性保障。