选择器
在可伸缩系统中,一个服务可以有多个节点提供。它们被部署在数据中心或者多个数据中心。
客户端如何选择一个节点来发起请求?你可以使用一个选择器来做这件事,它就像一个有路由逻辑的负载均衡器一样。
rpcx支持多种选择器,你可以在创建XClient的时候设置它。
随机选择
例程:random
选择器随机选择一个节点。
轮询
例程:roundrobin
轮询方式选择一个节点。
加权轮询
例程:weighted
使用平滑加权轮询均衡算法,实现了Nginx中相同的算法。
对于像{5,1,1}这样的边界情况加权,我们生成{a,a,b,a,c,a,a}顺序替换之前生成的{c,b,a,a,a,a,a}
算法如下:对于每一次节点选择,我们依据它的权重增加合适的节点的当前权重,选择当前权重最大的节点并将它的当前权重减少所有分布式节点的权重的总值。
加权ICMP
例程:ping
使用ping(ICMP)的结果来设置每个节点的权重。ping值越低,节点的权重越高。
假设t
是ping的耗时:
- 如果t<=10权重=191
- 如果10<t<=200权重=201-t
- 如果200<t<1000权重=1
- 如果t>=1000权重=0
一致性哈希
例程:hash
使用JumpConsistentHash算法来保证对于相同的服务路径、服务方法和参数路由到相同的节点。这是一个快速的一致性哈希算法。
如果节点改变,那么算法会重新计算一致性哈希。
地理位置
例程:geo
我们希望客户端选择一个最近的服务来发起请求。
服务必须在它们的元数据中设置地理位置。
如果有多个最近的服务,随机选择一个。
你应该在客户端中使用以下方法来设置地理位置,它会改变地理位置选择器的选择值。
func (c *xClient) ConfigGeoSelector(latitude, longitude float64)
用户自定义选择器
例程:customized
如果以上的选择器不适合你,你可以开发一个自定义的选择器。
选择器是一个接口:
type Selector interface {
Select(ctx context.Context, servicePath, serviceMethod string, args interface{}) string
UpdateServer(servers map[string]string)
}
- Select
:定义一个选择算法。
- UpdateServer
:客户端初始化节点,如果节点改变则更新节点。