基于Docker的负载均衡和服务发现
应用的容器化和微服务化带来的问题
- 在缺省网络模型中,容器每次重启后,IP会发生变动,在一个大的分布式系统保证IP地址不变是比较复杂的事情
- IP频繁发生变动,动态应用部署无法预知容器的IP地址,client端如何发现server端的访问端点?
解决方案(根据客户端是否有感知进行分类)
客户端的发现。client 订阅注册中心,有一个固定的注册中心地址,client订阅某个服务的注册中心,注册中心根据服务的运行状态推送某个服务的访问端点列表给client端。 该方案的实现举例有dubbo,DNS的解析等。
服务端的发现。服务端提供某个服务固定的访问端点,客户端直接访问该端点即可达到与服务端通信的目的,该访问端口对接后端具有动态IP的容器,作为请求的入口,负责请求转发到后端的容器。该方案的实现举例就是各种对后端负载均衡的实现,包括LVS/Nginx/HAProxy等。我们可以认为如下公式基本成立
"服务端的发现" = "负载均衡器" + "路由配置自动更新"
对比客户端的发现,服务端发现对客户端无感知,由于很多已有的应用或者系统并不是按照类似Dubbo这种服务化的框架实现的,这些应用或者系统的客户端对服务发现都是无感知的,因此服务端的发现就表现出了独特的优势。客户端的服务发现方法中,DNS是一个例外,几乎所有的客户端都支持DNS。下面介绍客户端DNS和服务端的负载均衡器做服务发现的几个方案。
服务发现方案
- DNS解析到多个IP
- 优点:Docker 版本大于1.10即原生支持容器集群内部DNS的服务发现。
- 缺点:由于DNS TTL生效时间的存在,解析的结果不能做到实时,即使TTL设置为0,某些应用或者方法库会缓存DNS解析的结果,导致会解析到已经失效的地址上
- 内核空间 LVS/IPVS
- 优点:IPVS的方案是docker在未来会正式发布的1.12版本中采用的方案,主要是做到了4层的负载均衡,请求的转发实现在内核中,不需要二次拷贝请求和响应的内容,不需要解析和处理7层HTTP协议,效率高
- 缺点:缺少7层负载均衡的支持,一个服务的负载均衡会占用主机的一个端口,服务与服务之间暴露的端口如果相同会产生冲突
- 用户空间 Nginx
- 优点:同时支持4层和7层负载均衡的代理,多进程模型方便利用多核性能,具有cache功能,亦可作为静态文件web服务器,7层可以根据区分HOST字段来复用同一个80端口,解决端口冲突的问题。7层负载会解析HTTP协议,支持多层路由,包括根据域名不同进行路由,根据路径不同进行路由,内部重定向等多种HTTP协议层的功能。
- 缺点:负载均衡调度算法较少,对后端进行健康检查的策略较少
- 用户空间 HAProxy
- 优点:同时支持用户空间4层和7层负载均衡的代理,是一个纯粹的软负载均衡器,支持Round-Robin,static-rr,least-conn,source-IP等多种调度算法,对后端进行健康检查的策略完备,包括TCP端口检查,HTTP请求检查,可执行程序检查等带外检查。7层可以根据区分HOST字段来复用同一个80端口,解决端口冲突的问题。7层负载会解析HTTP协议,支持多层路由,包括根据域名不同进行路由,根据路径不同进行路由,内部重定向等多种HTTP协议层的功能。
- 缺点:不能作为静态文件服务器,不支持cache缓存功能
aliyun容器服务的负载均衡解决方案
经过前面优缺点的分析和结合aliyun自身产品的优势,提供了以下解决方案。
- docker自带的DNS 服务发现,只要docker版本大于1.10(目前阿里云支持的docker最新版本为1.11),就支持DNS的服务发现。其特点是为1)每个容器提供独立的DNS解析;2)可以通过容器名与别名(aliases)方式在整个网络作用域内解析到某个容器的IP;3)通过链接别名的方式(link aliases)在容器的作用域内设置DNS解析,好处是不同容器的相同别名不会冲突。4)对外部的DNS解析请求进行代理。如下图所示
- 4层,提供阿里云的云产品SLB的负载均衡方案,底层是基于LVS做了改造和增强,SLB经受了长期线上实战的考验,稳定性和正确性可以得到保证。同时,容器服务在此基础上能做到监控容器部署的情况,随着服务的启停,动态绑定SLB后端的端口(稍后解释原理)。
- 7层,提供基于haproxy的负载均衡方案,支持灵活的配置。容器服务在此基础上能做到监控容器部署的情况,随着服务的健康状况,动态调整后端的负载(稍后解释原理)。
- 虽然我们4层主推SLB来做负载均衡,同时7层主推haproxy来做负载均衡,但是实际上SLB支持7层的负载均衡,底层基于Tengine,而HAProxy也支持用户空间4层的负载均衡,用户可以根据自己的情况,灵活选择/组合方案。
SLB做到动态绑定的原理:swarm监听容器的状态,如果容器正常运行,则把容器加入到SLB的后端,如果容器发现异常,则把容器从SLB的后端摘下来。
HAProxy实现动态服务发现的原理:HAProxy容器内除了有HAProxy软件,还有脚本程序监听容器的状态,根据容器的健康状况重新生成负载均衡信息,然后重新加载(reload) HAProxy,使得新的负载均衡信息生效。
实现不停服rolling_update原理:平滑升级的关键在于每一时刻均有至少一个容器还能正常提供服务。1)需要部署多个容器,将容器分为A,B两批更新。2)更新容器时,先将A批容器的路由从SLB或者HAProxy上面摘下来。3) 更新A批容器 4)A批容器健康检查正常后,重新加入路由 5)摘下B批容器的路由 6)更新B批容器。
实现灰度发布原理:不通版本的服务可以共享同一路由信息,通过调整SLB或者HAProxy权重的方式来做到灰度发布。
根据场景提供给用户的服务形态
- 简单路由服务:基于HAProxy,我们加了一层wrapper,做到动态发现处于运行状态的容器,加入到负载均衡中,我们称之为简单路由服务(routing service),其公网IP通过一个SLB对外进行暴露。主要解决如下需求:
- 7层服务端点对公网暴露,即承接公网访问集群内使用7层协议的服务的流量。
- 7层服务端点对内网暴露,即容器集群内的负载均衡和服务发现:如下图所示,集群内的服务发现利用了Docker自带的DNS resolver配合了HAProxy的负载均衡和健康检查。图中的LB即为简单路由服务下的HAProxy容器,1)首先通过Docker自带的DNS resolver将域名
restserver.local
解析到HAProxy容器的IP,此处会优先选择当前节点的HAProxy容器进行负载均衡;2)RestClient请求域名restserver.local
时,请求先走到代理容器LB;3)LB根据从Discovery Service
获取到的负载均衡信息代理到提供相应服务的容器后端RestServer Contaienr
。 - 不支持4层的路由
- 自定义路由服务:作为一个可选的容器,实现跟简单路由服务类似,解决如下需求:
- 通过环境变量和标签提供强大且灵活的配置支持,同时支持用户基于该容器进行扩展(通过
Dockerfile
FROM
的方式)。 - 支持用户空间的4层协议转发
- 通过环境变量和标签提供强大且灵活的配置支持,同时支持用户基于该容器进行扩展(通过
- SLB路由服务:将SLB绑定到某个服务上面,后端随服务的启停动态配置。主要解决如下需求
- 对外暴露的服务,使用4层协议,通过自定义SLB做4层的转发
- 容器间的4层或者7层通信,流量特别大时,推荐使用自定义SLB(内网)服务。
场景和对应的路由服务总结
layers S-N (ingress 入口通信) E-W (peer to peer 容器间通信) layer 4 SLB路由服务(公网) 自定义路由服务/SLB路由服务(内网,防止回路问题) layer 7 简单路由服务 简单路由服务/自定义路由服务 如上述图表所示,我们将容器集群外进入容器集群内的入口通信称为南北通信,将集群内容器和容器之间的流量成为东西通信。我们根据不同的通信形式和协议层提供不同的服务来满足用户的需求,例如对应南北通信,如果是使用7层协议的服务,我们推荐用户使用集群的SLB进行流量转发,最终的流量会转发到每个主机的HAProxy容器上面,然后在分发到相应的处理请求的服务上。
- 南北通信
- 指的是整个容器集群入口的通信。南北通信的特点往往是通信量比较大,因此我们首先用SLB将流量分散到各个主机节点。
- 东西通信
- 指的是集群内部,容器和容器间的通信方式
- docker自带的DNS 服务发现,只要docker版本大于1.10(目前阿里云支持的docker最新版本为1.11),就支持DNS的服务发现。其特点是为1)每个容器提供独立的DNS解析;2)可以通过容器名与别名(aliases)方式在整个网络作用域内解析到某个容器的IP;3)通过链接别名的方式(link aliases)在容器的作用域内设置DNS解析,好处是不同容器的相同别名不会冲突。4)对外部的DNS解析请求进行代理。如下图所示
基于Docker的负载均衡和服务发现的更多相关文章
- 在Windows环境中使用Nginx, Consul, Consul Template搭建负载均衡和服务发现服务
搭建负载均衡和服务发现服务的目的 随着网站业务的不断提升,单个服务器的性能越来越难满足客户的业务需求,所以很多情况下,需要使用多服务器实例和负载均衡器来满足业务需要. Nginx 什么是Nginx N ...
- QCon技术干货:个推基于Docker和Kubernetes的微服务实践
2016年伊始,Docker无比兴盛,如今Kubernetes万人瞩目.在这个无比需要创新与速度的时代,由容器.微服务.DevOps构成的云原生席卷整个IT界.在近期举办的QCon全球软件开发大会上, ...
- 实现基于Haproxy+Keepalived负载均衡高可用架构
1.项目介绍: 上上期我们实现了keepalived主从高可用集群网站架构,随着公司业务的发展,公司负载均衡服务已经实现四层负载均衡,但业务的复杂程度提升,公司要求把mobile手机站点作为单独的服务 ...
- 实现基于DNS的负载均衡
转自:http://blog.sina.com.cn/s/blog_4e424e2101000c3g.html 如果你有一个很受欢迎的Web站点,你会发现当请求的连接数增加时,服务器的响应延时也会随之 ...
- 通过Nginx、Consul、Upsync实现动态负载均衡和服务平滑发布
前提 前段时间顺利地把整个服务集群和中间件全部从UCloud迁移到阿里云,笔者担任了架构和半个运维的角色.这里详细记录一下通过Nginx.Consul.Upsync实现动态负载均衡和服务平滑发布的核心 ...
- Azure Load Balancer(二) 基于内部的负载均衡来转发为访问请求
一,引言 上一节,我们使用 Azure Load Balancer 类型为外部的,来转发我们的 Web 服务.今天我们看看另一种类型为 “Internal” 的 Azure Load Balancer ...
- Docker Swarm 负载均衡详解 or 模式选择
Docker Swarm 负载均衡详解 Swarm模式内置DNS组件,可以自动为集群中的每个服务分配DNS记录. Swarm manager使用内部负载均衡,根据服务的DNS名称在集群内的服务之间分发 ...
- 使用nginx sticky实现基于cookie的负载均衡
在多台后台服务器的环境下,我们为了确保一个客户只和一台服务器通信,我们势必使用长连接.使用什么方式来实现这种连接呢,常见的有使用nginx自带的ip_hash来做,我想这绝对不是一个好的办法,如果前端 ...
- Nginx基于TCP的负载均衡的配置例子
原文:https://blog.csdn.net/bigtree_3721/article/details/72833955 nginx-1.9.0 已发布,该版本增加了 stream 模块用于一般的 ...
随机推荐
- 解决 weblogic poi3.9 报错 a different type with name "javax/xml/namespace/QName"
解决 java.lang.LinkageError: loader constraint violation: loader (instance of weblogic/utils/classload ...
- 发现一个ReactNative大神
传送门: RN使用技巧:http://www.jianshu.com/p/2f575cc35780 RN 进阶技巧:http://www.jianshu.com/p/b877115fff1b 亮点有: ...
- XMLHttpRequest HTTP请求的返回码为0 http status = 0
由于用户在http返回前关闭/取消,或者防火墙等原因,会造成http请求没有status信息.w3c有相应的说明:http://www.w3.org/TR/XMLHttpRequest/#the-st ...
- V-rep学习笔记:main script and child scripts
The main and child scripts The main script and the child scripts, which are simulation scripts, play ...
- jQuery 绑定事件及移除绑定事件方法和元素事件列表
1.jQuery Event 事件: ready(fn); $(document).ready()注意在body中没有onload事件,否则该函数不能执行.在每个页面中可以有很多个函数被加载 ...
- jquery.uploadify 在firefox会出现httperror
原来是因为我的上传处理页面的page 继承了一个基类影响到的 然后这个基类 好像是因为在别的项目里面的原因 希望对也遇到这样的问题的人有帮助咯
- LPDMvvmKit 系列之 UITableView 的改造
阅读本文需要对ReactiveCocoa足够了解,也可以参阅图解ReactiveCocoa基本函数(http://www.jianshu.com/p/38d39923ee81) Cocoa Touch ...
- libev ev_init分析
/* these may evaluate ev multiple times, and the other arguments at most once */ /* either use ev_in ...
- 查看linux设备文件系统类型的方法
网络上找来找去没有找到简单的,最后翻了鸟哥的书就找到了,鸟哥的书还是真的有用心写的. /proc/filesystems 当前被内核支持的文件系统类型列表文件 /etc/filesystems 系统已 ...
- HDU 4324 Triangle LOVE (拓扑排序)
Triangle LOVE Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Tot ...