演讲 | 叶靖(又拍云系统开发工程师)
整理 | 不离
近日,又拍云Open Talk No.24在广州落幕,本次Open Talk的主题是“Docker与微服务的架构实践”,又拍云叶靖在活动中分享了“基于ngx_lua的动态服务路由方案”,详细介绍了又拍云在这方面积累的经验。
点击文末的“阅读原文”,获取又拍云Open Talk No.24 (Docker与微服务架构实践)的现场PPT与视频。
以下是叶靖的分享全文。
大家好,我叫叶靖,来自又拍云,主要负责云处理,刚才有老师给大家介绍了唯品会容器化平台的整个架构,其实又拍云也在做这样一件事情,这从另一方面可以理解成这个三件套已经广泛地被大家接受了,如果大家需要做容器化的时候,可以借鉴一下今天分享的内容。
我今天介绍的是 基于ngx_lua的动态服务路由, 是整个容器化过程中的一个组件。容器化在服务路由这一块有很大的挑战,又拍云通过自己的一些方案去解决它,而且这个方案也会开源出来,如果大家以后也碰到这样的问题,可以直接用这个方案。
如何做到服务的zero down_time的更新
在更新服务的时候,怎么能做到让自己的服务不断掉, 又拍云做更新的时候,不允许有失败,如果说因为我们的失败而导致请求失败,即使你的请求非常少,首先从口碑上就很不好;另外一个原因:如果造成了事故,是要赔钱的。这也是我们做动态服务路由的重要原因。
说到服务路由,大家都会想到三个方面:
服务注册、服务发现、负载均衡,服务注册说的是服务提供者在起来的时候,得去服务发现注册一下,以表明我提供了的服务、端口、IP是多少,服务名又是什么。
服务发现就是一个集中管理服务的地方,上面记录了有哪些服务,它们在哪些地方。
负载均衡,因为有很多同样的容器提供了同样的一个服务,怎么在这些容器里做负载均衡,也是要考虑的。
服务发现 有很多方案,ETC跟Consul算是后起之秀,比较常见。Zookeeper是一个比较老牌的开源项目,比较成熟,对资源的要求比较高,相对比较强大一点。Consul不但支持KV存储,还有原生的服务监控、多数据中心、DNS功能等,所以我们选了Consul这个方案。
负载均衡 也是有很多方案,比如说Nginx,LVS扩展起来非常难;再高级一点的有HA_PROXY,它可以做到高层的,也可以做到基层的,Nginx专注于做HTTP,后续也支持了TCP。从负载均衡出发,选择了Nginx。
如上图,我们把Nginx和Consul放在一张图里。为了突出服务这一块,我把一些跟服务不太有关系的都省略掉了。我们基于Mesos、Docker还有Marathon做了服务管理。其中有一个服务是特殊的,就是Registrator,它会通过Docker API在每个物理机上起一个容器,通过Docker API,把容器的状态定时的汇报给Consul,上面的Nginx是做负载均衡的,因为我们的服务目前来说都是基于Nginx直接到容器里面。
Consul里的服务如何更新到Nginx?
在这个图里面,Nginx到容器这一步是没有问题的,服务注册到配置文件也是没有问题的,但是从Consul到Nginx是有问题的,因为Consul有所有的信息,但是这些信息要如何通知给Nginx,一个新的服务起来了,或者是一个服务挂掉了,这些信息Consul知道了,怎么让Nginx把有一些有问题的给删掉,再把一些新写的给加进去,这就是我们要解决的一个问题。
面临的问题就是Consul里的服务如何更新到Nginx,如果解决了这个问题,刚才那个图就已经圆满。
市场上有很多方案来解决这个问题:
1. Consul_template
监听Consul里的key,会触发执行一个脚本,利用这个特性的服务,服务发生变动,会根据预先配置好的模板去重新生成配置,这个就是最后要执行的一个脚本。原理就是这样:
上图是一个例子,比如说一个模板是这样的,然后中间都是将来要被渲染的一些变量,如果K/v发生变动,模板化生成一份真实的配置文件,然后再执行一个本地的命令,Nginx -s reload,重新生成配置文件,Reload一下,这样新的服务就已经生效了。当然这样也有一些 问题: