go-zero微服务一些随想

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模式,以获得更好的可用性保障。