APP下载

基于分布式微服务系统的跨主机通信问题及其解决方案

2019-05-23周兵

电脑知识与技术 2019年5期
关键词:网络架构微服务分布式

周兵

摘要:传统单体式架构(Monolithic Architecture)的开发周期长、难维护、难测试等特征,越来越难适应当前互联网技术的发展需求,这也使得企业难以推进技术更新。随着移动互联网的发展,企业被迫将其应用迁移至现代化UI界面架构以便能兼容移动设备,这要求企业能实现应用功能的快速上线;此外,从技术方面看,云计算及互联网公司大量开源轻量级技术不停涌现并日渐成熟,比如:轻量级开发技术的出现如Spring Cloud;新的轻量级协议如RESTful API和轻量级消息机制;简化的基础设施如操作系統虚拟化如hypervisors;容器化如Docker,基础设施即服务(IaaS)如Kubernetes等; 新的可替代数据持久化模型如NoSQL等;标准化代码管理如Github等等。这一切都催生了新的架构设计风格——微服务架构的出现。

微服务天生就是分布式的,部署在各个主机上的服务系统会面临跨主机通信问题,如何设计一个高效、安全又能适应分布式微服务要求的网络架构,该文具有一定的指导意义。

关键词:网络架构;微服务;分布式;Docker;跨主机通信

中图分类号:TP393 文献标识码:A 文章编号:1009-3044(2019)05-0060-03

传统单体式架构(Monolithic Architecture)的开发周期长、难维护、难测试等特征,越来越难适应当前互联网技术的发展需求,这也使得企业难以推进技术更新。随着移动互联网的发展,企业被迫将其应用迁移至现代化UI界面架构以便能兼容移动设备,这要求企业能实现应用功能的快速上线。此外,从技术方面看,云计算及互联网公司大量开源轻量级技术不停涌现并日渐成熟,比如:轻量级开发技术的出现如Spring Cloud;新的轻量级协议如RESTful API和轻量级消息机制;简化的基础设施如操作系统虚拟化如hypervisors;容器化如Docker,基础设施即服务(IaaS)如Kubernetes等;新的可替代数据持久化模型如NoSQL等;标准化代码管理如Github等等。这一切都催生了新的架构设计风格——微服务架构的出现。

微服务天生就是分布式的,部署在各个主机上的服务系统会面临跨主机通信问题,如何设计一个高效、安全又能适应分布式微服务要求的网络架构是当前面临的一个普遍问题。

1 分布式微服务

1.1 什么是微服务

“微服务”源于2014年3月Martin Fowler所写的一篇文章“Microservices”。微服务软件架构是一种软件设计模式,一种互联网软件系统架构,它将单体式应用划分成一些小的服务,服务之间互相协调、互相配合,为用户提供服务。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于HTTP的RESTful API)。每个服务都围绕着具体的业务功能进行构建开发,并且能够被独立地部署到生产环境或开发环境中。在分布式系统中,还要允许服务可重复部署。微服务是一种架构风格,一个大型的复杂的软件应用被切分成一个或多个微服务组成。系统中的各个微服务可被独立部署运行,各个微服务之间是松耦合的,互不依赖。每个微服务仅关注于完成一件任务或者说一个单一的功能,并能很好地完成该任务。在所有情况下,每个任务代表着一个小的业务功能。

1.2 单体式架构系统

传统的软件架构是一个项目一个应用,这个应用不能重复安装部署,也就是只能安装在一台服务器上,因此无须考虑对应用进行多服务器部署,也就不用考虑各节点之间的网络通信问题。这种架构的最大特点是安装部署简单,但由于不能横向扩展,需要一般需要性能强劲的专业服务器设备。由于采用单服务器部署,系统将不可避免地会发生单点故障,单个服务器发生故障的时候会波及整个系统或者网络,从而导致整个系统或者网络的瘫痪。这种架构的缺点很明显,随着需求和功能增加,系统将越来越大,功能间的依赖会越来越复杂,难维护、扩展性差、升级困难。

1.3 分布式架构系统

分布式系统架构是把一组独立主机划分为逻辑主机,同时对外提供服务,对于用户来说,逻辑主机和独立主机都是不可见的,就像是一台主机在提供服务一样。分布式架构的优势之一是可以使用廉价硬件(相对于昂贵的专业服务器),另一个优势是提高了系统的可靠性,可扩展性。主机越多,CPU、内存、存储资源等也就越多,能够处理的用户并发访问量也就越大。比如一个大型网站,一般会把一个网站横向拆分成很多小功能模块,然后把不同的功能模块部署到不同的服务器上,各个功能模块之间通过远程服务调用(RPC)等方式进行通信,以一个逻辑主机的形式对外提供服务。这些拆分的小功能模块,也就是微服务的雏形。

1.4 分布式微服务架构

分布式微服务架构本身是一种去中心化的架构,即微服务是跨机房、可重复部署的,是跨机房负载均衡的,用户在访问这个微服务的时候,为其提供服务的主机和机房是不确定的,并且微服务随时可以在任意不同的服务商或机房之间迁移和部署。

2 微服务与Docker容器

Docker使用Google公司推出的Go语言进行开发实现,基于Linux内核对进程进行封装隔离,属于操作系统层面的虚拟化技术。由于隔离的进程独立于宿主和其他的隔离的进程,因此也称其为容器。

在Docker技术出现之前,微服务架构是很难实现的。因为微服务系统需要一套独立的执行环境,这套环境不能对外部有依赖性。同时,执行环境的粒度又必须足够的小。Docker在容器的基础上,进行了进一步的封装,极大简化了容器的创建和维护,粒度足够小,是一个很优秀的微服务运行环境。

Docker是一种虚拟化技术,如何使网络中的容器们可以相互通信,又能让容器外部网络的用户访问这些容器呢?

3 跨主机网络通信问题

没有跨主机网络时,比如一个应用有两个服务,两个服务不可能部署到同一个机器上,这样没办法做到高可用,所在的主机一旦出现故障,主机上所有的服务都将无法访问。如果将服务部署到两个主机上面,但是两个主机上面这个容器的IP在主机外面是看不到的。所以只能把容器的IP转换成了一个宿主机的一个IP,或者宿主机的一个访问端点,才能让外部的主机访问。所以,传统方案是通过端口映射,把容器的一个端口映射到主机的一个端口,让另外一个主机和这个主机映射到这个容器上去通信。这样会带来一些问题,首先通过端口映射,比如说映射到8090端口,如果还要启动另一个容器,就需要映射到另外一个端口,因为宿主机上只有这一个8090端口,不可能共享同一个端口。映射出去之后是宿主机的一个端口,这样这个端口就是对外暴露的,安全性需要严格控制。

在Docker1.9之后,增加了跨主机的网络,它就可以直接通过容器的IP去通信,通过这个外部跟它是隔离的,这样又能做到安全,启动多个容器,容器的IP端口也是不会冲突的。

3.1 VXLAN封包模式

VXLAN封包模式,比如overlay驱动,它是用VXLAN的协议去把容器之间的请求封装成VXLAN的请求,将链路层的以太网包封装到UDP包中进行传输。首先举个例子,从C1去访问宿主机上C2的容器,先通过C1发出这个包之后,它首先进行封包,要查找中心化存储C2是在哪个主机上的,查到的是这个主机上,就把这个请求的包封装成宿主机之间的包,把这个包送达到对应宿主机上,再通过一定的约定去解包,最终转发到另外一个主机上的一个容器。其缺点是对带宽的损耗比较大,因为看到这里去封包,它肯定是把这个容器的包上面又加了一层包,这个包上面肯定会有一些自己的占用,一般像封包模式,MTU最终都会小于宿主机之间的MTU,它还会造成一些资源占用。比如说在这个地方去封包的时候,它可能会占用CPU去做一下封包操作,还会占用CPU去做解包的操作,所以会增加主机上的负载,但是它的好处是对基础设施要求比较低,它只需要两个宿主机之间可以三层互通。

Docker的overlay驱动也是封包模式的实现,它的封包方式是基于VXLAN。VXLAN内部把一个二层的包、链路层的一个请求封装成一个VXLAN的一个包,这里面会有一个约定的信息,比如VXLAN ID,还有一个外部的UDP的头,最终会把这个包通过UDP发往对应的主机上面去,对应的主机再做VXLINE的解包。Docker还会做IP的地址管理和网络信息同步。

3.2 路由模式

举例来说,主机1上的容器想要访问主机2的容器,首先这个机器上是没有主機2的IP地址,它出了机器之后到达路由器,再通过路由器上的路由表,去把对应的请求网端转发到对应的主机2上面,主机2上面是有这个容器的IP,所以它就能够做到这个容器的跨主机通信。它的好处在于它没有封包,所以它的性能很好,但是它对于基础设施有一些要求,比如我的基础设施要支持、能够配置这个路由表,如果用Linux路由要支持二层的转发。

3.3 两种模式优缺点比较

总的来说,二层VLAN网络需要二层网络设备支持,通用性和灵活性不如Overlay网络。相比之下,Overlay网络在不改变现有网络基础设施的前提下,通过某种约定通信协议,把二层报文封装在IP报文之上的新的数据格式。能够充分利用成熟的IP路由协议进程数据分发,突破VLAN的数量限制,并可将广播流量转化为组播流量,避免广播数据泛滥。因此,Overlay网络实际上是目前最适合的Docker容器跨节点通信方案。

4 分布式微服务架构系统的跨主机网络通信解决方案与实施

4.1 案例说明

n如图所示,假设本地局域网段10.159.62.0/24中存在主机10.159.62.231,10.159.62.232和10.159.62.233互联互通;

n每个主机上都运行Docker引擎,通过Docker运行若干个Docker容器,例如图中的Order,Billing等;

n将这3台主机建立成为一个Docker Swarm集群;

n创建一个Docker Overlay网络(网段10.10.0.0/24),每个主机上的容器都被加入该overlay网络中,通过overlay网络实现跨主机的容器相互通信;

n假设Console,Terminal和API这三个服务均需要暴露端口到物理网络,因为物理网络10.159.62.0/24无法直接访问overlay网络中的容器,需要容器中映射端口到物理网络。

noverlay网络中的容器默认通过与主机之间的bridge访问物理网络。

4.2 开放Docker Swarm集群所需的主机端口

Swarm集群的成员主机都需要开放集群所需的主机端口:

firewall-cmd --zone=public --add-port=2377/tcp --permanent

firewall-cmd --zone=public --add-port=7946/tcp --permanent

firewall-cmd --zone=public --add-port=7946/udp --permanent

firewall-cmd --zone=public --add-port=4789/tcp --permanent

firewall-cmd --zone=public --add-port=4789/udp --permanent

firewall-cmd –reload

4.3 创建Docker Swarm集群

Docker Swarm是Docker开源组织提供的Docker环境集群管理工具,它能够把若干台Docker主机的抽象为一个逻辑上的主机,它也是一种用于统一管理Docker主机的CLI工具,可用来控制Docker主机。Swarm调用的是Docker API标准接口,兼容非集群模式的操作指令,比如通过常规的docker运行命令来启动容器,Swarm会自动选择适合的主机来运行相关容器。也就是说,像Compose编排脚本可以在不经任何改动的情况下,直接通过Swarm来实现对集群的管理。

创建Docker Swarm集群命令:

docker swarm init --advertise-addr

将其他Docker主机节点加入Swarm集群中:

docker swarm join \

--token SWMTKN-1-49nj1cmql0jkz5s954yi3oex3nedyz0fb0xx14ie39trti4wxv-8vxv8rssmk743ojnwacrr2e7c \

192.168.99.100:2377

查看集群所有服务器节点:

docker node ls

至此,Docker Swarm集群创建完毕。

4.4 构建Overlay network

Swarm上默认已有一个名为ingress的Overlay网络,也可以自定义创建新的Overlay网络。Docker提供给我们两种方式来定义overlay网络,在docker1.12之前,我们需要依靠第三方的工具如Consul、Etcd或者ZooKeeper来实现“服务发现”和“DNS解析”,从而实现不同主机之间的多个容器之间的网络通信。但是在docker1.12之后,我们可以直接用Docker原生的swarm来实现“服务发现”和“DNS解析”。

创建指定子网的Overlay跨主机网络,也可不指定子网IP,由系统自动指定:

docker network create \

--driver overlay \

--subnet 10.0.9.0/24 \

--gateway 10.0.9.99 \

my-network

4.5 在跨主机的网络上部署一个服务

docker service create \

--replicas 3 \

--name my-web \

--network my-network \

nginx

选项--replicas为微服务应用重复部署的数量。其他管理命令:

docker service ls 查看集群列表

docker service ps lvs 查看集群下所有节点状态

docker service rm lvs 删除集群

docker service inspect --pretty lvs 集群属性

docker service scale lvs=4 #扩容集群节点数量

4.6 验证测试

首先进入容器内部:

docker exec -ti 容器id /bin/bash

使用ping命令測试:

ping 容器name

5 结论

当我们开发好微服务之后,考虑到灵活快速持续部署的需要,通常会考虑将其Docker容器化并在Docker环境下运行。由于微服务个数通常会较多,把所有微服务部署在一台Docker主机上是不现实的,因此需要考虑到跨主机通信的问题,对实际部署必然会提出以下几点要求:

1)微服务作为一个Docker容器可以在任意主机上运行;

2)同一主机上可以运行多个相同或不同的微服务;

3)运行在同一个主机上的微服务之间可以相互通信;

4)运行在不同主机上的微服务也可以相互通信;

5)每个微服务的IP地址不受主机所在本地局域网IP地址段限制,即拥有独立网段,避免占用本地IP地址,同时确保容器数量受限尽量小;

6)每个微服务容器避免通过端口暴露的方式相互通信,确保不会因端口独占而导致无法灵活部署。

综上所述,采用在Docker Swarm模式下将各微服务加入同一个overlay network网络的方式实现微服务之间的跨主机通信是现实可行的方案。

参考文献:

[1] 王磊.微服务架构与实践[M].北京:电子工业出版社,2016.

[2] sam newman.微服务设计[M]. 北京:人民邮电出版社,2016.

[3] 王福强.springboot揭秘:快速构建微服务体系[M]. 北京:机械工业出版社,2016.

[4] 周立.spring cloud与docker微服务架构实战[M]. 北京:电子工业出版社,2017.

【通联编辑:代影】

猜你喜欢

网络架构微服务分布式
微信公众平台在医院图书馆的应用现状调查
从单一模式系统架构往微服务架构迁移转化技术研究
基于DDS的分布式三维协同仿真研究
西门子 分布式I/O Simatic ET 200AL