如何设置路由规则

安装示例程序

如果你还没有安装示例程序,请参照 快速开始 安装 Aeraki,Istio 及示例程序。

安装完成后,可以看到集群中增加了下面两个 NS,这两个 NS 中分别安装了基于 MetaProtocol 实现的 Dubbo 和 Thrift 协议的示例程序。 你可以选用任何一个程序进行测试。

  1. ~ kubectl get ns|grep meta
  2. meta-dubbo Active 16m
  3. meta-thrift Active 16m

请求级别的负载均衡

Istio 会使用 TCP proxy 来代理非 HTTP 协议的客户端请求,同一个客户端 TCP 连接上发出的所有请求都会被发送到一个服务器实例。这导致了一个问题:当客户端使用长连接时,多个服务器实例收到的请求不够均衡,当服务端压力过大时,即使及时扩容也不能将已有服务端的压力分担出去。

Aeraki 支持对基于 MetaProtocol 开发的任何协议进行七层(请求级别)负载均衡,因此在不进行任何配置的情况下,客户端的代理会将请求均匀发送到两个不同版本的服务器端。 下面我们用 aerakictl 命令来查看客户端的应用日志,可以看到同一个客户端连接上的多个请求被依次发送到了 v1 和 v2 两个服务器端。

  1. ~ aerakictl_app_log consumer meta-dubbo -f --tail 10
  2. Hello Aeraki, response from dubbo-sample-provider-v2-7546478cbf-l2l74/172.16.0.37
  3. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  4. Hello Aeraki, response from dubbo-sample-provider-v2-7546478cbf-l2l74/172.16.0.37
  5. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  6. Hello Aeraki, response from dubbo-sample-provider-v2-7546478cbf-l2l74/172.16.0.37
  7. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89

按任意属性将请求路由到某个指定版本的服务

MetaProtocol 支持了非常灵活的路由匹配条件,任何可以从协议数据包中解析出来的属性都能用于路由匹配条件。

备注:Aeraki 会按照服务的 VIP 建立 Listener,每个服务独享 Listener,避免了 HTTP 协议的同端口多服务带来的路由表膨胀问题,路由表中只包含本服务相关的路由信息,极大地提高了路由查询效率。

创建一条 MetaRouter 路由规则,将请求路由到 v1:

  1. kubectl apply -f- <<EOF
  2. apiVersion: metaprotocol.aeraki.io/v1alpha1
  3. kind: MetaRouter
  4. metadata:
  5. name: test-metaprotocol-dubbo-route
  6. namespace: meta-dubbo
  7. spec:
  8. hosts:
  9. - org.apache.dubbo.samples.basic.api.demoservice
  10. routes:
  11. - name: v1
  12. match:
  13. attributes:
  14. interface:
  15. exact: org.apache.dubbo.samples.basic.api.DemoService
  16. method:
  17. exact: sayHello
  18. foo:
  19. exact: bar
  20. route:
  21. - destination:
  22. host: org.apache.dubbo.samples.basic.api.demoservice
  23. subset: v1
  24. EOF

使用 aerakictl 命令来查看客户端的应用日志,可以看到客户端的所有请求都被路由到了 v1 版本:

  1. ~ aerakictl_app_log consumer meta-dubbo -f --tail 10
  2. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  3. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  4. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  5. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  6. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  7. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89

流量拆分

使用 MetaRouter 路由规则将客户端的流量按照指定比例发送到不同版本的服务。

  1. kubectl apply -f- <<EOF
  2. apiVersion: metaprotocol.aeraki.io/v1alpha1
  3. kind: MetaRouter
  4. metadata:
  5. name: test-metaprotocol-dubbo-route
  6. namespace: meta-dubbo
  7. spec:
  8. hosts:
  9. - org.apache.dubbo.samples.basic.api.demoservice
  10. routes:
  11. - name: traffic-split
  12. match:
  13. attributes:
  14. interface:
  15. exact: org.apache.dubbo.samples.basic.api.DemoService
  16. method:
  17. exact: sayHello
  18. foo:
  19. exact: bar
  20. route:
  21. - destination:
  22. host: org.apache.dubbo.samples.basic.api.demoservice
  23. subset: v1
  24. weight: 20
  25. - destination:
  26. host: org.apache.dubbo.samples.basic.api.demoservice
  27. subset: v2
  28. weight: 80
  29. EOF

使用 aerakictl 命令来查看客户端的应用日志,可以看到客户端的请求按照 MetaRouter 中设置的指定比例发送到了 v1 和 v2:

  1. ~ aerakictl_app_log consumer meta-dubbo -f --tail 10
  2. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  3. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  4. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  5. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  6. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  7. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  8. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89
  9. Hello Aeraki, response from dubbo-sample-provider-v2-7546478cbf-l2l74/172.16.0.37
  10. Hello Aeraki, response from dubbo-sample-provider-v2-7546478cbf-l2l74/172.16.0.37
  11. Hello Aeraki, response from dubbo-sample-provider-v1-6b7cc9b6f8-j9dvl/172.16.0.89

理解原理

在向 Sidecar Proxy 下发的配置中, Aeraki 在服务对应的 Outbound Listener 的 FilterChain 中设置了 MetaProtocol Proxy,并在 MetaProtocol Proxy 配置中指定 Aeraki 为 RDS 服务器。

Aeraki 会将 MetaRouter 中配置的路由规则翻译为 MetaProtocol Proxy 的路由规则,通过 Aeraki 内置的 RDS 服务器下发给 MetaProtocol Proxy。

可以通过下面的命令查看 sidecar proxy 的配置:

  1. aerakictl_sidecar_config consumer meta-dubbo |fx

其中 Dubbo 服务的 Outbound Listener 中的 MetaProtocol Proxy 配置如下所示:

  1. {
  2. "name":"envoy.filters.network.meta_protocol_proxy",
  3. "typed_config":{
  4. "@type":"type.googleapis.com/udpa.type.v1.TypedStruct",
  5. "type_url":"type.googleapis.com/aeraki.meta_protocol_proxy.v1alpha.MetaProtocolProxy",
  6. "value":{
  7. "stat_prefix":"outbound|20880||org.apache.dubbo.samples.basic.api.demoservice",
  8. "application_protocol":"dubbo",
  9. "rds":{
  10. "config_source":{
  11. "api_config_source":{
  12. "api_type":"GRPC",
  13. "grpc_services":[
  14. {
  15. "envoy_grpc":{
  16. "cluster_name":"aeraki-xds"
  17. }
  18. }
  19. ],
  20. "transport_api_version":"V3"
  21. },
  22. "resource_api_version":"V3"
  23. },
  24. "route_config_name":"org.apache.dubbo.samples.basic.api.demoservice_20880"
  25. },
  26. "codec":{
  27. "name":"aeraki.meta_protocol.codec.dubbo"
  28. },
  29. "meta_protocol_filters":[
  30. {
  31. "name":"aeraki.meta_protocol.filters.router"
  32. }
  33. ]
  34. }
  35. }
  36. }

在导出的文件中还可以查看到目前 Proxy 中生效的 RDS 路由信息,如下所示:

  1. {
  2. "@type":"type.googleapis.com/aeraki.meta_protocol_proxy.admin.v1alpha.RoutesConfigDump",
  3. "dynamic_route_configs":[
  4. {
  5. "version_info":"1650265656",
  6. "route_config":{
  7. "@type":"type.googleapis.com/aeraki.meta_protocol_proxy.config.route.v1alpha.RouteConfiguration",
  8. "name":"org.apache.dubbo.samples.basic.api.demoservice_20880",
  9. "routes":[
  10. {
  11. "name":"traffic-split",
  12. "match":{
  13. "metadata":[
  14. {
  15. "name":"interface",
  16. "exact_match":"org.apache.dubbo.samples.basic.api.DemoService"
  17. },
  18. {
  19. "name":"method",
  20. "exact_match":"sayHello"
  21. },
  22. {
  23. "name":"foo",
  24. "exact_match":"bar"
  25. }
  26. ]
  27. },
  28. "route":{
  29. "weighted_clusters":{
  30. "clusters":[
  31. {
  32. "name":"outbound|20880|v1|org.apache.dubbo.samples.basic.api.demoservice",
  33. "weight":20
  34. },
  35. {
  36. "name":"outbound|20880|v2|org.apache.dubbo.samples.basic.api.demoservice",
  37. "weight":80
  38. }
  39. ],
  40. "total_weight":100
  41. }
  42. }
  43. }
  44. ]
  45. },
  46. "last_updated":"2022-04-18T07:07:36.165Z"
  47. }

最后修改 April 18, 2022: fix issue (92db845)