微服务中若干关键问题的研究及应用

微服务中若干关键问题的研究及应用

摘要

微服务软件架构正处于兴起阶段,Netflix、亚马逊等互联网公司的成功案例表明微服务在大规模企业应用中有较明显的优势。本文介绍微服务架构的概念,分析微服务架构的优点和缺点,对微服务实践中的三个问题进行详细阐述,即:通信、服务发现、服务部署。为了满足项目对可伸缩性和高可用性的要求,设计了基于微服务的架构方案,采用微服务和容器结合的虚拟化方式,构建了基础服务,在此之上根据业务需求组合基础服务形成应用服务。

关键词:微服务,服务治理,虚拟化,基础服务

Research and Implementation on Some Key Problems of Micro-service

Abstract

Micro-service software architecture is in the stage of exploration. Netflix,
Amazon and other Internet companies’ success stories show that micro-service
have obvious advantages in large-scale enterprise applications. This paper
introduces the concept of micro-service architecture, analyzes the advantages
and disadvantages of micro-service architecture, and elaborates three problems
in micro-service practice, namely, communication, service discovery and service
deployment. In order to meet the requirements of project’s scalability and high
availability, the architecture scheme based on micro-service is designed.
Combining micro-service and container, we build some basic services. On this
basis, according to the business demand, applications are built perfectly.

Key words: micro-service,service management,virtualization,basic services

目录

1 引言

2 微服务的优点和缺点

3 微服务的关键问题分析

3.1 服务间通信问题

3.1.1 RPC框架

3.1.2 REST

3.1.3 基于事件的异步通信

3.1.4 API Gateway

3.2 服务发现

3.3 服务部署

4 微服务的实际应用

5 结论

参考文献

引言

微服务[1]是一种架构风格,微服务的概念起源于2014年3月Martin
Flowler所写的一篇文章[2],尽管微服务这种架构没有明确的定义,但是具有一些共同的特性:协同工作的小而自治的服务。按照微服务架构的思想,将复杂的应用分解为多个微小的服务,这些服务运行在各自的进程中,使用与语言无关的轻量级通信机制相互协调,每个服务围绕各自的业务进行构建,可使用不同的编程语言和存储技术,并能够通过自动化机制独立部署。

任何事情都不是一蹴而就的,微服务架构也是如此,图1描述了应用架构的演进的历史[3]。具体阐述如下:

图1

MVC架构:当业务规模很小时,将所有功能都部署在同一个进程中,通过双机或者前置负载均衡器实现负载分流,此时,用于分离前后台逻辑的MVC架构是关键。

RPC架构:当垂直应用越来越多,应用之间交互不可避免,将核心和公共业务抽取出来,作为独立的服务,此时,用于提高业务复用及拆分的RPC框架是关键。

SOA架构:随着业务发展,服务数量越来越多,服务生命周期管控和运行态的治理成为瓶颈,此时用于提升服务质量的SOA成为关键。

微服务架构:随着敏捷开发、持续交付、DevOps理论的发展和实践,以及基于Docker等轻量级容器(LXC)部署应用和服务的成熟,微服务架构开始流行,逐渐成为应用架构未来的演进方向。通过服务的原子化拆分,以及微服务的独立打包、部署和升级,小团队敏捷交付,应用的交付周期将缩短,运维成本也将大幅下降。


微服务的优点和缺点

微服务的思路是将单一的巨大应用拆分为众多松耦合的微小服务,通常是按照业务功能来分解的,每一个服务虽然小但却实现完整的功能,使用私有的数据库,可以单独构建和部署,单个服务的修改和部署不影响其他正在运行的服务,提供语言无关的API接口供其他模块调用,这种风格与传统的面向服务架构SOA[4]比较相似,经过多年的发展,SOAP、Web
Services、ESB[5]等技术的出现使SOA得以实现,众多厂商也制定了相关标准,两者最重要的区别在于SOA使用复杂的ESB集成为单一应用,而微服务是轻量级的,松耦合,可以独立部署。微服务可由不同的团队独立开发,互不影响,而且微服务架构对持续交付是一种巨大的推动力,允许在频繁发布不同服务的同时保证系统其他部分的可用性和稳定性。

虽然微服务架构的一些想法是好的,但当整体实现时也会呈现出复杂性,其缺点体现在:

1.
必须有坚实的DevOps[6]开发运维一体化技能:开发人员需要熟知运维环境,而运维人员也需掌握必要的技术,譬如NoSQL等,具有较强DevOps技能的人员比较稀缺,会带来招聘人才方面的挑战。

2.
性能问题:微服务应用中每个服务都运行在独立的进程中,服务之间的调用需要通过网络传输,当众多服务需要相互调用时,就要考虑网络延迟对系统的影响了。

3.
数据一致性问题:微服务本质上也是一个分布式系统,那么就避不开数据一致性这个问题,事实上微服务架构中解决数据一致性问题的确比单体应用中困难。

微服务架构有利有弊,在考虑是否使用微服务架构时,需要权衡利弊,结合实际业务场景,做出正确的选择。

微服务的关键问题分析

服务间通信问题

微服务是一个分布式系统,服务被部署在不同的节点中,服务的交互需要通过网络进行通信,因此服务间的通信是一个需要考虑的问题,它会直接影响整个系统的性能。

首先要考虑的问题是,服务间的通信应该采用的模式,即同步还是异步,这个基础性的选择会不可避免的引导我们使用不同的实现。如果使用同步通信,发起一个远程服务调用后,调用方会阻塞自己并等待整个操作的完成,而异步通信调用方不需要等待操作完成即可返回,甚至可能不需要关心这个操作完成与否。这两种通信模式对应各自的协作风格,即请求/响应模式和基于事件模式。对于前者来说,客户端发起一个请求,然后等待响应,这种模式可以很好的匹配同步通信,但是异步通信也可以采用这种模式,客户端发起请求,然后注册回调,当服务端操作结束后,会调用该回调。对于后者来说,情况则完全不同,客户端不是发起请求,而是发布一个事件,然后等待其他的协作者接收该消息,并且知道该怎么做,基于事件的系统天生就是异步的,客户端发布一个事件,但并不需要知道谁会对此做出响应,这也意味着,可以在不影响客户端的情况下对该事件添加新的订阅者。

针对请求/响应方式,可以考虑两种技术:RPC(Remote Procedure
Call,远程过程调用)和REST[7](Representational State
Transfer,表述性状态转移)。开源RPC框架有很多,按照偏重的功能来划分,分为服务治理型和跨语言调用型,服务治理型RPC框架有淘宝的dubbo[8]、新浪的motan[9],跨语言调用型RPC有Thrift[10]、gRPC[11]等等。

针对基于事件的异步通信,则可以借用众多成熟的消息系统,如RabbitMQ[12]、Apache
Kafka[13]等,它们都支持多种语言接口,并且提供持久化的、异步的、高性能的消息通信机制,对于复杂的微服务,使用消息系统的优势很明显,它实现了服务间的解耦,并且解决了分布式系统中的可靠性问题。

RPC框架

由于篇幅限制,挑选典型的两个框架进行介绍,即dubbo和thrift。

dubbo是一个分布式服务框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案,其核心部分包含:

远程通讯:提供对多种基于长连接的NIO框架抽象封装,包括多种线程模型、序列化、以及“请求-响应”模式的信息交换方式。

集群容错:提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错、地址路由、动态配置等集群支持。

自动发现:基于注册中心目录服务,使服务消费方能动态查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。

Thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发,它结合了功能强大的软件堆栈和代码生成引擎,以构建在多种语言之间无缝结合的、高效的服务。

REST

REST是受WEB启发而产生的一种架构风格,REST风格包含了很多原则和限制,我们专注于在微服务的世界里使用REST更好地解决集成问题。REST是RPC的一种替代方案。

REST本身没有提到底层应该用什么协议,但HTTP天生与REST搭配,HTTP本身提供了很多功能,这些功能对实现REST风格非常有用,譬如说,HTTP的动词GET、PUT、POST就能很好地和资源一起使用。

对比于RPC,基于HTTP的REST有优点也有缺点,优点是:有许多很好的HTTP客户端库可供使用,客户端和服务端代码完全解耦;缺点是:在要求低延迟的场景下,每个HTTP请求的封装开销是个大问题;需要自己动手实现支持高级的序列化和反序列化机制。

基于事件的异步通信

基于事件的异步通信主要考虑两部分:微服务的发布事件机制和消费者接收事件机制。传统上来说,像RabbitMQ、zookeeper[14]这样的消息代理能够处理上述两个问题,生产者(producer)使用API向代理发布事件,代理也可以向消费者提供订阅服务,并在事件发生时通知消费者。这种代理甚至可以追踪消费者的状态,比如标记哪些消息是该消费者已经消费过的。这种系统常用具有较好的可伸缩性和弹性,但这么做也是有代价的,它会增加开发流程的复杂度,因为你需要一个额外的系统(消息代理)才能开发测试服务。开发人员也需要额外的机器和专业知识来保持这些基础设施的正常运行,一旦实施成功,它会是实现松耦合、事件驱动架构的一种有效方法。

API Gateway

考虑如下场景,一个使用微服务架构的应用既支持web网站又支持手机原生应用,各微服务通过API接口对上述两个客户端提供后台服务,展示手机上的一屏画面可能就需要调用多个后台微服务,因为移动设备通常带宽较低且流量资费高昂,这种频繁的调用会增加时延并影响用户体验。

API
Gateway是进入系统的唯一节点,它封装内部系统的架构,并且提供API给各个客户端,它还可以提供譬如授权、监控、负载均衡、缓存、请求分片和管理、静态响应处理等。图2展示了使用API
Gateway后的架构。

图2

API Gateway的开源实现常见的有Netflix API Gateway和基于Nginx的Kong[15]。

服务发现

当一个微服务需要调用另一个微服务时,如何定位其网络位置是一个关键问题。出于系统伸缩的需要,微服务会有很多实例,他们被部署在一台或者多台机器中,网络位置是动态的,因此需要一种服务发现机制。简单的服务发现方案是DNS,DNS让我们将一个名称与一个或多个机器IP地址相关联。DNS最主要的优点是简单易行、灵活方便,几乎所有的技术栈都支持,然而,尽管很多组件可以管理组织内的DNS,但其中很少是为处理这种高度可控制主机的场景而设计的,这使得更新DNS条目有些困难。所以现在更多使用的是动态服务注册。

如图3所示,服务实例在启动时向服务注册中心注册自己,当服务实例失效时注册中心会自动注销该实例地址,客户请求时,先向服务注册中心查询,得到可用的服务实例地址后再进行访问。

图3

服务注册中心在整个去中心化的大趋势下貌似格格不入,但其实这是解决问题的最佳方法,但这时也需要考虑单点故障问题,当系统规模较大、要求较高时需要使用集群,目前已有满足这种需求的开源实现,如zookeeper、consul、etcd。

服务部署

微服务的部署时另一个需要考虑的重要问题。主要由以下几种方法:A.
微服务实例都部署在一台或多台虚拟机或物理主机中,不需要特别的隔离办法,只要保证每个微服务都拥有不同的端口或者位置。譬如Java
Web应用可以让多个微服务的war文件都部署在同一个tomcat中。这种方法简单直接,共享系统资源,利用率最高,但缺点是没有服务间隔离,某个服务由于bug抢占系统资源可能造成所有服务不可用,另外一个缺点是需要根据微服务所使用的技术栈部署各种运行环境,延长了交付周期,没能实现持续交付。B.
让每个微服务实例运行在单独的虚拟机中,这种隔离方法最彻底,互相不受影响,并可以控制每台虚拟机使用资源的额度,对某个服务的扩展也变得简单,缺点是虚拟机本身消耗资源且启动缓慢。C.
随着轻量级容器技术的飞速发展,可以将每个微服务实例部署在docker等容器中,每台虚拟机可运行一个或多个容器实例。容器属于操作系统层面的虚拟化,提供了类似虚拟机的完全隔离环境,但却共享系统内核,占用资源少,启动速度快,而且随着系统的逐步变大,可以使用容器集群管理系统,譬如kubernetes[16]、docker
swarm、Mesos[17]等,他们兼具服务发现功能,大大减轻了服务部署和伸缩的难度。

微服务的实际应用

数据工程项目的建设目的是根据试验通信信息服务的特点,研究数据应用在试验通信信息服务中应用的关键技术和难点,并以此研究数据应用技术的现状趋势,技术内容涵盖数据工程中数据采集、数据存储、数据处理、数据应用等各个环节,在确定技术体系的基础上,根据测通所提供的“通信词条”和“通信设备故障”数据资源,对数据应用技术软件原型体系架构、接口、数据库等进行详细设计,并完成软件原型。

项目后端的总体框架如图4所示,该项目中采用了微服务架构,可以大体忽略具体业务逻辑,从架构设计来看:
图4

  1. 最底层是docker容器,docker容器对主机的资源进行了充分隔离,而且使用mesos来管理docker实例。

  2. 基础服务层,可以随意分配给不同的人员来使用不同的技术栈进行开发,得益于docker容器层,基础服务启动时向注册中心zookeeper注册。

  3. 应用服务层,如果业务需要经典的MVC架构来实现,此时可以通过组合基础服务层来实现。

  4. UI层,可以同时支持PC客户端和手机客户端,手机客户端通过API
    Gateway来访问微服务。

结论

本文阐述了正在兴起的微服务架构的概念和原理。与传统单体式应用架构相比,微服务架构降低了系统耦合度,增强了系统持续交付能力,提高了系统的可扩展性。对微服务中的三个关键问题(通信问题、服务发现问题及服务部署问题)进行了较为详细的阐述,提出了各种场景下实现微服务架构的不同路径及其优劣,为微服务的系统设计提供了一些指引。最后结合今年部门的数据工程项目,从架构层面上阐述了微服务的思想。得益于微服务架构,该系统具有较强的可扩展性和容错能力,且同时支持WEB客户端和手机客户端,能为客户提供稳定优质的数据查询等服务。

参考文献

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

[2] FOWLER M, LEWIS J. Microservices [J]. Viittattu, 2014, 28: 2015.

[3] 李林锋.分布式服务框架原理与实践[M].北京:电子工业出版社,2016:23-24.

[4] EINAS H. Service-oriented architecture: scaling the uber engineering
codebase as we grow [EB/OL].(2013-10-30) [2015-07-05].
https://eng.uber.com/soa/.

[5] wiki. esb[EB/OL]. https://en.wikipedia.org/wiki/Enterprise_service_bus.

[6] BASS L, WEBER I, ZHU Liming. DevOps: A software architect’s perspective [M].
Sydney: Addison-Wesley Professional, 2015.

[7] stackoverflow. What is exactly RESRful programming[EB/OL].
http://stackoverflow.com/questions/671118/what-exactly-is-restful-programming.

[8] alibaba. dubbo[EB/OL]. http://dubbo.io/.

[9] weibocom. motan[EB/OL]. https://github.com/weibocom/motan.

[10] SLEE M, AGARWAL A, KWIATKOWSKI M. Thrift: scalable cross-language services
implementation [R].[S.l]: Facebook White Paper, 2007.

[11] Google. gRPC[EB/OL]. https://grpc.io/.

[12] rabbitMQ[EB/OL]. http://www.rabbitmq.com/.

[13] Apache. kafka[EB/OL]. http://kafka.apache.org/.

[14] Apache. zookeeper[EB/OL]. http://zookeeper.apache.org/.

[15] Kong-API Gateway[EB/OL]. https://getkong.org/.

[16] Google. kubernetes[EB/OL]. https://kubernetes.io/.

[17] Apache. Mesos[EB/OL]. http://mesos.apache.org/.