微服务架构下的核心话题 (二):微服务架构的设计原则和核心话题

 

前期回顾:html

微服务架构下的核心话题 (一):微服务架构下各种项目的顺势崛起算法

1、前言

     毫无疑问,微服务架构的设计原则和核心话题是本文要讨论的重点,也是打算从零基础开始构建微服务架构须要事先考虑、规划的。一个好的产品、应用可否稳定运行,持续开发,知足业务需求,可否经得起现实的考验,就须要在设计阶段考虑不少、不少,以确保它的健壮性。数据库

    当咱们从单体架构的应用走向基于微服务的架构时,首先会面临一个很棘手的问题是如何进行服务的拆分,服务的拆分粒度应该如何衡量,怎样拆分的服务才算是“微”。接着将又会面临,这么多的服务又如何关联起来呢?如何有效的相互间通讯呢?如何高效的部署呢……跨域

     本文我将从微服务架构的设计原则、核心话题两大方面展开讨论,但愿可以对你构建一个微服务架构的应用有所帮助。安全

 

2、微服务架构的设计原则

      软件架构的设计原则、方法论,在很大程度上可以指导、提醒咱们应该遵循什么的原则、规范,能让软件架构更加健壮、稳固,并易于开发、扩展、维护等。服务器

1.拆分足够微

     在解决复杂的问题时,咱们倾向于将问题划分红若干个小问题来解决,所谓“大事化小,小事化了”。单体架构的应用,随着时间的推移,会变得愈来愈臃肿,愈来愈难以维护,适当的作“减法”,能够解决单体架构存在的这些问题。微信

     将单体架构的应用拆分为微服务架构的应用时,服务的拆分粒度问题,成为了重中考虑的问题。粒度太大,拆分的不够充分,便和单体架构没有太大的区别,更不能发挥出微服务的优点。若是拆分的太细,又将会面临着服务数量太多而引起的服务管理、服务间调用的问题。对于如何“微”才算是足够的“微”,是没有标准的衡量计算方法的。网络

    微服务不是说越小越好。服务越小,微服务架构的优势和缺点也就会愈来愈明显。服务越小,微服务的独立性就越高,但同时微服务的数量也会增长,管理就会存在很大的问题,成为一个新的挑战,这也就是经常所被提到的“这么多的服务,该服务管理啊?”问题。架构

    服务的拆分足够微,能够按照某种方式、规则拆分,一般能够按照业务模块、业务场景等进行拆分,尽可能避免服务间的相互依赖,作到高内聚低耦合。紧密关联的处理,放在一个服务内,但避免在服务与服务之间共享数据。并发

2.轻量级通讯

      在单体架构的应用中,可直接经过简单的方法调用就能进行通讯,但在微服务架构中,因为服务都是跨域进程,甚至是跨主机的,组件只能经过REST、Web服务或RPC相似的机制在网络上进行通讯。

      由于服务划分的已经足够小了,服务间的通讯可能会比较频繁,考虑到性能、响应时间等方面,则服务间通讯应采用轻量级的通讯协议,如:同步的REST,异步的AMQP、STOMP、MQTT等。在实时性要求不高的场景下,采用REST通讯是不错的选择,REST是基于HTTP协议,可方便进行跨域访问或跨防火墙的设置,而且消息格式能够统一为XML或JSON格式,方便开发人员阅读和理解。若是服务间通讯比较频繁,有比较高的要求,可采用消息通讯的方式,如:Kafka、MQ等相似的消息中间件。若是不考虑对外提供访问的话,可采用gRPC的通讯方式,由于gRPC是基于Netty的,通讯效率更高。

3.单一职责原则

     当服务粒度过粗时,服务内部很容易产生耦合。若是多人开发同一个服务,很容易由于耦合过大形成代码修改重合,不利于后期维护。确保每一个服务职责单一,这也是用来肯定服务拆分边界的一个原则,遵循“高内聚、低耦合”。

    必需要对本身的产品和业务的了解,才能更准确的肯定服务边界,让各个服务知足单一的业务职责,避免职责交叉。

4.领域驱动原则

     领域驱动设计(Domain Driven Design),是一套综合软件系统分析和设计的面向对象建模方法。一个微服务,就应该可以反映出某个业务的领域模型,使用领域驱动设计,不但能够下降微服务环境中通用语言的复杂度,并且能够帮助团队搞清楚领域的边界,理清上下文边界。

    建议将每一个微服务都设计成一个DDD限界上下文,为微服务提供了一个逻辑边界。每一个独立的团队负责一个逻辑上定义好的系统切片,负责与一个领域或业务功能相关的所有开发,最终团队开发出的代码更加易于理解和维护。

(关于DDD更详细的了解,可参考https://www.cnblogs.com/edisonchou/p/edc_ddd_foundation_study_part1.html)

 

3、微服务架构的核心话题

      基于微服务架构的应用,将面临着许多选择、争议等讨论的核心话题,这些核心话题将会在你接下来的微服务架构生涯里不断出现,并成为讨论的焦点。在此,我以为有必要进行汇总整理,让你以为它存在的必要性,能为你之所用。

1.服务拆分

       服务拆分首先关注的就是服务的颗粒度,可遵循设计原则——拆分足够微,经过DDD(领域驱动设计)的指导,将某个领域的功能进行聚合成为一个服务。

       对于一个大型复杂的单体应用而言,选择先拆分哪一个模块,是一个问题。通常考虑先从容易、简单被拆分的模块开始,在拆分简单模块过程当中,不断积累微服务的经验,逐步拆分掉复杂、繁重业务的核心模块。同时,寻找那些和其余功能业务重合度低、耦合度低,且自身变化较为缓慢的基础服务,将它们拆分为微服务。

      决定了拆分哪些模块,要拆分红多个微服务后,接下来就要划清服务拆分的边界,将服务边界和接口顺理清楚。肯定哪些应该包含进来,哪些不该该包含进来,哪些接口须要从新设计,哪些能够重复利用。

      以下图所示,展现了一个单体应用拆分为多个微服务的过程。一旦拆分完后,各个服务就能够独立开发、部署和扩展。

     服务的拆分,不仅仅指功能的拆分,如上图所示,还得考虑数据库的拆分 ,确保下降功能逻辑层、数据访问层的耦合度。

2.服务注册与发现

      微服务架构的特色是服务的数量众多,这些众多的服务须要一个统一的服务注册平台来进行服务的管理。每一个微服务实例在启动后,将本身的实例信息注册到服务注册表或服务注册中心。服务的调用方若想获取可用服务实例的列表,则须要从服务注册表中去获取相关的信息。

      当服务实例失效或down掉之后,服务实例的信息就要从服务注册表中移除,即:服务注销。服务注册表是用于维护全部可用的服务实例的地方,服务注册表一方面要接收微服务实例的接入,另外一方面当服务实例不可用时,须要及时将服务实例从注册表中清楚。下图展现了服务注册与服务实例的关系。

       服务注册与发现组件或框架,有不少,如:Eureka、Consul、etcd等,都提供了服务注册表的功能,可供你们进行选择。

3.负载均衡

       在微服务架构中,负载均衡是必须使用的技术,经过它来实现系统的高可用、集群扩容等功能。负载均衡一般分为两种:服务端负载均衡和客户端负载均衡。一般所说的负载均衡均指服务器端的负载均衡,可经过软件或硬件设备来实现,软件如:Nginx、LVS等,硬件如:F五、A10等,硬件负载均衡设备成本较高,大部分采用的是软件方式。架构图以下:

       经过软件或硬件实现负载均衡都会维护一个服务端清单,利用心跳检测等手段进行清单维护,保证清单中都是能够正常访问的服务节点。当用户发送请求时,会先到达负载均衡器(通常做为一个服务),负载均衡器根据负载均衡算法(轮训、随机、加权轮训)从可用的服务端列表中取出一台服务端的地址,接着进行转发,下降系统的压力。

4.API网关

       考虑到微服务架构中服务的数量不少,为了便于服务对外统一的管理,API网关的引入是必不可少的。API网关旨在提供统一的API入口点,来管理多个服务内部API,可方便实现对平台众多服务接口进行管控,如对访问服务的身份认证、业务鉴权、流量并发控制、API调用的计量或计费等。

      API网关经常使用于如下场景:

  • 黑白名单:实现例如经过IP地址来禁止访问某些服务的某些功能。
  • 日志:实现日志访问的记录,用于分析访问、处理性能指标,并将分析结果提供给其余模块使用,如:运维平台的统计功能。
  • 协议适配:实现通讯协议校验、适配转换的功能。
  • 身份认证:负责外部系统的访问身份认证。
  • 计流限流:实现微服务访问流量计算,基于流量计算分析进行限流等。
  • 路由:API网关的核心功能,实现请求的转发。

     API网关的引入为微服务架构应用带来诸多的好处,以下:

  • 避免将内部信息/接口泄露给外部: 可以将对外发布的API与微服务内部的API区分开来,使得各个微服务在添加或变动时,能有明确的安全边界,避免多过的对外暴露。
  • 为微服务添加额外的安全层:可以提供一套额外的保护层,用以应对SQL注入、Dos攻击等,其中系统的权限控制能够再这一层来实施。
  • 支持多种混合通讯协议:考虑到微服务架构中,各个微服务的平台与语言的多样性,一般将对外提供基于HTTP或REST的API接口,而内部微服务将根据自身服务状况采用不一样的通讯协议(如:ProtoBuf、RPC等)。API网关则跨域这些内部不一样协议的微服务,提供一个基于REST的统一外部API。
  • 减低构建微服务的复杂性:基于微服务架构应用的复杂性,如API令牌、访问控制、限速限流等,每一项功能的添加,对会额外对各个服务带来影响,从而影响微服务的开发周期。这些功能若是在API网关上统一处理,则会从代码层面进行了有效的隔离,使得不会影响其余微服务,这样更有利于其余微服务只需关注于实际的业务开发。

    常见的API网关实现方式不少,如:Nginx、Kong、Spring Cloud Zuul、Træfɪk等。

5.服务部署与发布

     单体应用被拆分为微服务后,随着微服务的数量增多,部署就成了问题,使得部署的复杂性提升了很多。因此,微服务的部署更加倾向于使用具备相互之间隔离的主机/虚拟机来实现服务的部署,使得服务可以独立的部署、测试、发布、升级。

    目前比较好的服务部署方式就是把各个微服务打包成Docker镜像,这样就保障避免了不一样主机环境对部署产生的影响。使用Docker部署,并结合Jenkins进行CI/CD,使得构建、发布、启动变得更加快捷。

    下图就是服务部署、发布流程。

 

4、总结

       一个微服务架构的应用,从最初的设计到逐步成型,是须要通过不断的迭代开发、摸索来完善的,上述只是列举出了我我的认为须要重点关注的点,以供你们参考,若有遗漏不足,望你们建议补充、完善。

 

欢迎微信扫码下面二维码,关注微信公众号【程序猿技术大咖】,进行更多交流学习!