全部产品
存储与CDN 数据库 域名与网站(万网) 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网 钉钉智能硬件
容器服务

集群内服务间路由和负载均衡

更新时间:2018-01-20 13:01:20

在容器服务上可以通过 acsrouting 将基于域名的 HTTP 服务暴露出去,而且能够配合健康检查自动的负载均衡和服务发现,当其中一个容器出现问题之后,routing 会自动将健康检查失败的容器从后端摘除,所以能做到自动的服务发现。然而这个是将服务暴露到外网环境。

那么集群内服务间如何通过这种方式做到自动的服务发现和负载均衡呢?阿里云容器服务中的 routing 容器具备负载均衡的功能,您只需要使用以 .local 结尾的域名,让容器仅能被集群内的其他容器所访问,然后配合 external_links 标签,从而实现集群内服务间发现和负载均衡。

实现原理

  1. 利用了 Docker 1.10 之后支持在容器中做别名的方式,在依赖负载于 restserver.local 的 restservice 容器中, restserver.local 域名实际解析的是 routing 容器的地址,restclient 服务发起请求时,首先将 HTTP 请求转发到 routing 容器,并带上 HOSTrestserver.local 的请求头。

  2. routing 容器会对配置 aliyun.routing_port_xxx: restserver.local 标签的容器健康状态进行监听,并将其挂载到 HAProxy 的后端,HAProxy 接收到带有 restserver.local HOST 头的 HTTP 请求后,就能转发到对应的容器。

图

优势

  • 相对于使用 link 或者 hostname 的基于 DNS 的方式,首先不同客户端对 DNS 缓存的处理不一致会导致服务发现的延迟性,其次 DNS 的方案也只有 round robin,不能满足微服务的场景需求。
  • 而相对于其他的微服务服务发现的解决方案,本方案提供了一个实现无关的服务发现和负载均衡机制,无需 server 端和 client 应用做任何修改即可使用。
  • 服务生命周期是解耦的,每个微服务可以采用一个 docker-compose 模板独立部署,更新。相互之间只是通过一个虚拟域名实现动态绑定即可。

编排示例

在下面的编排示例中,为 restserver 服务增加 aliyun.routing.port_80: restserver.local标签,确保只有集群内的容器可以访问这个域名。然后为 restclient 服务配置 external_links,指向 restserver.local 这个域名。reclient 服务便可以这个域名访问到 restserver 服务,并且能够配合健康检查做到自动的服务发现。

  1. restserver: # 模拟 rest 服务
  2. image: nginx
  3. labels:
  4. aliyun.routing.port_80: restserver.local # 使用 local 的域名,只有集群内的容器可以访问这个域名
  5. aliyun.scale: "2" # 扩展出两个实例,模拟负载均衡
  6. aliyun.probe.url: "http://container:80" # 定义容器的健康检查策略是 http,端口是 80
  7. aliyun.probe.initial_delay_seconds: "2" # 健康检查在容器起来之后两秒之后再检查
  8. aliyun.probe.timeout_seconds: "2" # 健康检查超时时间,如果两秒还没返回认为不健康
  9. restclient: # 模拟 rest 服务消费者
  10. image: registry.aliyuncs.com/acs-sample/alpine:3.3
  11. command: "sh -c 'apk update; apk add curl; while true; do curl --head restserver.local; sleep 1; done'" #访问 rest 服务,测试负载均衡
  12. tty: true
  13. external_links:
  14. - "restserver.local" #指定 link 的服务的域名。请确保您设置了 external_links,否则访问会失败。

然后,通过如下的 restclient 服务的日志,您可以看到 restclient 的 curl 的 http 请求被路由到不同 rest 服务的容器上,容器 ID 分别为 053cb232fdfbcb5405ff791650a0746ab77f26cce74fea2320075c2af55c975fb8c36abca525ac7fb02d2a9fcaba8d36641447a774ea956cd93068419f17ee3f

  1. internal-loadbalance_restclient_1 | 2016-07-01T06:43:49.066803626Z Server: nginx/1.11.1
  2. internal-loadbalance_restclient_1 | 2016-07-01T06:43:49.066814507Z Date: Fri, 01 Jul 2016 06:43:49 GMT
  3. internal-loadbalance_restclient_1 | 2016-07-01T06:43:49.066821392Z Content-Type: text/html
  4. internal-loadbalance_restclient_1 | 2016-07-01T06:43:49.066829291Z Content-Length: 612
  5. internal-loadbalance_restclient_1 | 2016-07-01T06:43:49.066835259Z Last-Modified: Tue, 31 May 2016 14:40:22 GMT
  6. internal-loadbalance_restclient_1 | 2016-07-01T06:43:49.066841201Z ETag: "574da256-264"
  7. internal-loadbalance_restclient_1 | 2016-07-01T06:43:49.066847245Z Accept-Ranges: bytes
  8. internal-loadbalance_restclient_1 | 2016-07-01T06:43:49.066853137Z Set-Cookie: CONTAINERID=053cb232fdfbcb5405ff791650a0746ab77f26cce74fea2320075c2af55c975f; path=/
  9. internal-loadbalance_restclient_1 | 2016-07-01T06:43:50.080502413Z HTTP/1.1 200 OK
  10. internal-loadbalance_restclient_1 | 2016-07-01T06:43:50.082548154Z Server: nginx/1.11.1
  11. internal-loadbalance_restclient_1 | 2016-07-01T06:43:50.082559109Z Date: Fri, 01 Jul 2016 06:43:50 GMT
  12. internal-loadbalance_restclient_1 | 2016-07-01T06:43:50.082589299Z Content-Type: text/html
  13. internal-loadbalance_restclient_1 | 2016-07-01T06:43:50.082596541Z Content-Length: 612
  14. internal-loadbalance_restclient_1 | 2016-07-01T06:43:50.082602580Z Last-Modified: Tue, 31 May 2016 14:40:22 GMT
  15. internal-loadbalance_restclient_1 | 2016-07-01T06:43:50.082608807Z ETag: "574da256-264"
  16. internal-loadbalance_restclient_1 | 2016-07-01T06:43:50.082614780Z Accept-Ranges: bytes
  17. internal-loadbalance_restclient_1 | 2016-07-01T06:43:50.082621152Z Set-Cookie: CONTAINERID=b8c36abca525ac7fb02d2a9fcaba8d36641447a774ea956cd93068419f17ee3f; path=/

本文导读目录