路由

在大型的微服务系统中,我们会为同一个服务部署多个节点, 以便服务可以支持大并发的访问。它们可能部署在同一个数据中心的多个节点,或者多个数据中心中。

那么, 客户端该如何选择一个节点呢? rpcx通过 Selector来实现路由选择, 它就像一个负载均衡器,帮助你选择出一个合适的节点。

rpcx提供了多个路由策略算法,你可以在创建XClient来指定。

注意,这里的路由是针对 ServicePathServiceMethod的路由。

随机 {#random_selector}

示例: random

从配置的节点中随机选择一个节点。

最简单,但是有时候单个节点的负载比较重。这是因为随机数只能保证在大量的请求下路由的比较均匀,并不能保证在很短的时间内负载是均匀的。

轮询 {#roundrobin_selector}

示例: roundrobin

使用轮询的方式,依次调用节点,能保证每个节点都均匀的被访问。在节点的服务能力都差不多的时候适用。

WeightedRoundRobin {#weighted_selector}

示例: weighted

使用Nginx 平滑的基于权重的轮询算法

比如如果三个节点abc的权重是{ 5, 1, 1 }, 这个算法的调用顺序是 { a, a, b, a, c, a, a },
相比较 { c, b, a, a, a, a, a }, 虽然权重都一样,但是前者更好,不至于在一段时间内将请求都发送给a

网络质量优先 {#ping_selector}

示例: ping

首先客户端会基于ping(ICMP)探测各个节点的网络质量,越短的ping时间,这个节点的权重也就越高。但是,我们也会保证网络较差的节点也有被调用的机会。

假定t是ping的返回时间, 如果超过1秒基本就没有调用机会了:

  • weight=191 if t <= 10
  • weight=201 -t if 10 < t <=200
  • weight=1 if 200 < t < 1000
  • weight=0 if t >= 1000

一致性哈希 {#hash_selector}

示例: hash

使用 JumpConsistentHash 选择节点, 相同的servicePath, serviceMethod 和 参数会路由到同一个节点上。 JumpConsistentHash 是一个快速计算一致性哈希的算法,但是有一个缺陷是它不能删除节点,如果删除节点,路由就不准确了,所以在节点有变动的时候它会重新计算一致性哈希。

地理位置优先 {#geo_selector}

示例: geo

如果我们希望的是客户端会优先选择离它最新的节点, 比如在同一个机房。
如果客户端在北京, 服务在上海和美国硅谷,那么我们优先选择上海的机房。

它要求服务在注册的时候要设置它所在的地理经纬度。

如果两个服务的节点的经纬度是一样的, rpcx会随机选择一个。

比必须使用下面的方法配置客户端的经纬度信息:

  1. func (c *xClient) ConfigGeoSelector(latitude, longitude float64)

定制路由规则 {#user_selector}

示例: customized

如果上面内置的路由规则不满足你的需求,你可以参考上面的路由器自定义你自己的路由规则。

曾经有一个网友提到, 如果调用参数的某个字段的值是特殊的值的话,他们会把请求路由到一个指定的机房。这样的需求就要求你自己定义一个路由器,只需实现实现下面的接口:

  1. type Selector interface {
  2. Select(ctx context.Context, servicePath, serviceMethod string, args interface{}) string
  3. UpdateServer(servers map[string]string)
  4. }

-Select: defines the select algorithm.
-UpdateServer: clients init the nodes and update if nodes change.