编者按:5 月 7 日下午在成都举办的“架构师实践日”沙龙中,来自长虹的软服云部研发主管李伟向大家做了题为“长虹 Docker 实践”的分享。李伟从多个方面阐述了 Docker 在长虹云端的实践。以下是对他的演讲内容的整理。
曾任职于成都中联信通科技有限公司,从事中国银联手机支付后台研发工作,对电商支付系统有一定的工作经验积累,对大型网站架构有深入研究。现任职于长虹电器股份有限公司软件与服务中心,担任软件架构师,负责各基础服务模块的架构设计与实现,以支撑长虹智能硬件、O2O 电商等业务。
长虹技术栈
图1 为长虹的技术栈。在长虹中,Java 占比 80%以上。
长虹在服务端的开发中采用了如图二所示的基础架构。在这里,已经使用了服务化以及分布式缓存、本地缓存、运行、数据库访问模块等概念,并且做了一个比较简单的数据库的储存。同时服务之间进行服务化,应用之间通过 MQ 进行解耦。
为何选用 Docker?
为什么会选用 Docker?其实 Docker 是一个非常新的技术,而长虹接触 Docker 比较晚,2014 年才开始,真正使用是始于 2015 年。
Docker 有五个优点:
持续部署与测试,Docker天生支持持续集成/持续部署。
跨云平台的支持。长虹有自建的数据中心,但也有不少业务是运行在公有云上,所以在程序或者应用的开发过程中,需要考虑跨云平台的支持,支持快速的迁移。
环境的标准化和版本控制。在大公司里,团队经常会考虑使用同一套运行环境、框架等等,比如说 Java 1.6 或者 1.7,这个要规范起来非常困难,而通过 Docker 做到运营环境的标准化则比较容易。
高资源利用率与隔离。
容器跨平台性与镜像。
图3 是传统虚拟化与 Docker 虚拟化的对比图。我们可以发现 Docker 的使用明显节约了资源,减少了虚拟机操作系统的资源占用。如果仅为单机,虚拟机操作系统在使用时耗用的资源是可以容忍的,但如果规模较大,就会造成巨大浪费。
Docker 化实践
目前,Docker 在业界的使用非常广泛,它官方的标准镜像也非常多。
图四为 Docker 化实践的三个简单步骤,首先编写 Docker File ,然后 build 镜像,最后根据指定镜像运行容器。
Docker 私有 Registry 扩展
使用 Docker 时,我们需要经常播一些官方的镜像,而在使用过程中我们不会把私有的镜像放到官方的 Docker Hub 中,所以我们会考虑自建 Docker 私有仓库。Docker 私有仓库官方提供两个版本,一个是使用 Registry V1 ,基于 Python 实现,它的效用比较低。二是使用 Registry V2,使用 Go 语言实现,上传、下载速度等各方面有一定性能优化,但是仍然存在一些不足,譬如它有登录鉴权但没有较细粒度的权限控制控制功能。
针对基于 Namespace 权限的控制,有两个解决思路。一是在基于官方 Registry 代码实现,二是通过代理。
通常权限控制需求大概如:指定公开路径、不做授权,开发者路径由开发者 push 到对应的一个路径下。测试人员 pull 开发者提供的镜像,测试通过以后,镜像可以通过 Docker Tag 打上一个新的标签,push 到生产 Namespace 下。
对于 Docker Hub,需要用一个 Web 界面管理长虹的镜像,由管理员对开发者的权限进行管理。另外 Docker Registry 的搜索功能比较弱,Docker Registry V2 目前为止没有提供镜像删除功能。图五是长虹的一个 Docker 私有 Registry 及 Hub 的实现思路。
Docker 与持续集成
图6 是长虹内部利用 Gitlab-ci Runner 构建 Golang 的一个示例。Gitlab-ci Runnner 可以运行在云主机、物理机、Docker 容器中。在这里采用了 Docker 容器运行 Gitlab-ci Runner。Gitlab-ci 的使用很简单,在每一个项目里,通过编写.gitlab-ci.yml 配置文件实现该工程通过 Gitlab-ci 持续集成。在构建的过程中,当 push 代码会触发 Gitlab-ci Runner 去自动构建代码,然后测试的结果会返回到界面。以持续集成通过单元测试,决定是否合并代码到 master 分支。如果你的代码通过了,可以在 Docker 里面自建 Docker View,然后直接构建 Docker 镜像,把镜像 push 到资源仓库中。
图7 是一个简单的示例,即利用 Gitlab-ci Runner 构建 Java maven 工程。
图8 是利用 Gitlab-ci Runner 构建、使用 Karma 框架测试 Angularjs 工程的一个示例,它在长虹的内部测试,以及外部开发中都会用到。Web 前端测试需要集成指定浏览器的支持,需要制作特定的镜像支持。图八中引用的镜像使用了 Firefox 浏览器测试前端代码。
Docker 网络
在中国,真正把 Docker 用到线上业务的公司并不多,有可能有极个别,但都不是用在核心业务之中。因为 Docker 比较新,本身还不够成熟,主要表现在 Docker 的网络层面。
Docker 本身提供了五个网络方式:
第一,Docker 指定的网络方式是你可以选择不为容器提供任何网络功能。
第二,与主机共享 Root Network Namespace。
第三,与另一运行容器共享 Network Namespace。
第四,利用网桥。如果你是个人开发者,你可以用使用这种网络模式部署集群,因为你的用户量和集群规模较小。但如果你的业务的用户量和集群规模很大,那么目前 Docker 的网络情况就会体现出来,这就是它饱受诟病的地方。
第五,通过 Bridge Vxlan 来实现跨主机划分子网。
因此,目前有很多第三方云计算公司抓住了这个机会,做了很多 SDN 的方案。Weave、Flannel、CALICO、Socket Plane 这四个是相对来说比较主流的四个第三方网络解决方案。
Weave 是由 Docker 实现的。一般情况下,我们主要是从控制和转发两个层面去理解 Docker 第三方网络解决方案的好处和弊端。Weave 的控制层面并没有使用类似基于 etcd 服务发现的技术,而是基于网络学习。它网络层面的主要缺点是不支持服务自动发现、不能自动识别 IP,需要手动进行配置。
Flannel 是目前用的最多的一个解决方案,也是目前长虹比较倾向使用的一个解决方案。Flannel 本身是采用 etcd 来作为 IP 的分发,两个主机之间 UDP 封包通信,主机内部通过网桥通信。
Socket Plane 与前几个解决方案的最大区别是使用虚拟交换机。两个主机之间通信采用 OVS (虚拟交换机)实现,性能较好。
微服务架构 vs 整体架构
在服务端架构设计中,长虹也将业务解耦服务化。SOA 与微服务的核心都是服务化,而且微服务的架构也并没有很确切的定义。但是当我们将微服务架构与传统的架构进行对比,就可以发现它们的区别,微服务架构是将传统架构中的模块/组件演变为独立的服务、通过网络通信(RPC)调用。 微服务的优点是模块独立,低耦合、迭代速度快、技术多样性、容错性高、拓展性好、测试方便。它的缺点是设计要求高,系统复杂度增加,团队要求增加,运维成本增加。
为什么要将 Docker 和微服务联系起来讲?原因是 Docker 容器技术的出现使得微服务更加易于实现。Docker 容器作为微服务的载体,当我们把微服务部署到 Docker 中时,应用更容易迁移、部署和发布。Docker 镜像的一致性可以理解为对应微服务的水平扩展副本,功能解耦是基于 Docker 镜像独立完整性。数据分区可以理解为 Docker 与数据服务结合。
在微服务架构设计中,有多种设计模式,比如分支模式或者聚合模式,图13所示的异步消息解耦模式在长虹服务端开发中使用较多。微服务之间本身有依赖关系,每一个微服务都有自己独立的缓存和 DB。
服务化的核心是服务治理。服务治理中主要有两个概念,即服务发现和负载均衡。长虹在 Java 中使用 Dubbo 框架服务化,但是原生 Dubbo 在 Docker 容器中部署时会有问题。但可以通过技术手段修正。
常用的 HTTP 负载均衡是采用 Nginx 反向代理不同的 Server,每个 Server 代理不同的 App,这种方式不支持服务自动发现。可通过 confd,etcd 来实现 RESTFul Web Service 负载均衡、服务自动发现。每个 App 在 Server 上运行后,向 etcd 注册服务,confd 修改 nginx 配置文件,然后 reload Nginx,这样在部署后面 Server 时,它可以做到服务的自动注册发现。
图16是基于 confd、etcd、HAproxy 、Docker 容器中的微服务应用的服务发现与负载均衡。
获取架构师实践日第七期视频回放链接,请在七牛云公众号后台回复关键词:71