转载

火爆开发概念之——微服务实践篇

什么是微服务?

目前,后端开发比较火爆的概念就是微服务,微服务是软件领域现阶段无人不提的话题,也是未来的一个发展方向。然而,据调查和了解,很多开发者将微服务下的单体应用和SOA(面向服务架构)服务治理下的单体应用混为一谈,认为二者是一样的模式,大量的系统在十几年前都已经是以SOA为基础的分布式系统了,那么微服务作为新的架构标准与SOA有什么差异点呢?其本质区别在于设计原理,微服务是去中心化设计,SOA是「集成」形成中心设计的。

火爆开发概念之——微服务实践篇

至于那些伴随着微服务理念而产生的持续集成、持续部署等概念,它们本身与敏捷、DevOps是交织在一起的,CICD更倾向于软件工程的领域,与微服务无关;还有Docker等容器化技术,也与微服务概念无关,它只是服务部署于何种介质之上。微服务可以采用持续集成,持续部署,可以用Docker部署,SOA服务体系下的应用,同样也可以。当然,DevOps(软件工程领域概念)、持续部署、敏捷开发(软件开发模式),Docker容器化技术(基础设施),这些领域的变革,带来思想上的创新和解脱,有力地推动了微服务架构的大行其道,二者相辅相成,彼此促进,助推软件领域的进步。微服务是一种架构理念,一种架构风格,它的精髓在于微,而微的精髓在于对服务的切分上。对一个产品或者一个项目的需求了解程度和深入理解程度,决定了服务切分的正确性,如果切分的不正确,它所带来的麻烦将比单体应用更难以解决。如何正确的划分某一个需求下所需要的服务体系呢,如何来有效的组织他们,划分每个服务的边界体系,很多年以前Eric Evans 在《领域驱动设计》提出的Domain Driven Design(领域驱动设计,DDD)概念,非常完美的解释了这个问题,书中关于领域驱动设计概念,以至于我首次接触微服务时,惊奇地发现,微服务模式下的系统设计不就是领域驱动设计里面的领域模型吗?

火爆开发概念之——微服务实践篇

《实现领域驱动设计》

领域驱动设计的核心概念是领域。同一个领域的系统都具有相同的核心业务,因为他们要解决的问题的本质是类似的。因此可以推断:一个领域本质上可以理解为一个问题域 。只要确定了系统所属的领域,那么这个系统的核心业务,即要解决的关键问题就基本确定了。而要成为一个领域的专家,必须要在这个领域深入研究很多年才行,只有积累了丰富的经验,这样才会遇到非常多的该领域的问题。通常情况下,一个领域有且只有一个核心问题,我们称之为该领域的「核心域」。在核心域、通用子域、支撑子域梳理的同时,会定义出子域中的「限界上下文」及其关系,用它来阐述子域之间的关系。界限上下文可以简单理解成一个子系统或组件模块。例如,下图是在我们的项目中对消息管理子域和界限上下文的梳理:

火爆开发概念之——微服务实践篇

采用通用的语言描述相关的领域内的问题,让设计人员、开发人员、需求师、业务人员都能很好的理解相关概念,通过相互交流,产生一个个领域模型,并在此基础上进行扩展,如上图所述,我们将每一个子域独立成微服务架构体系下的一个个服务应用,明晰每一个开发者所负责的领域需要完成的工作和需求所描述的含义。

实践讲解

下面我将以项目实践为例来讲解微服务。先简单描述一下项目背景,统一消息平台项目是银行希望在互联网环境下能够统一对外发布消息,对行内各渠道系统各业务部门发布的消息进行集中管控。

我们的项目正好赶上银行敏捷开发转型行内推广,该项目作为试点项目,采用了敏捷开发的模式,全体项目组成员经历了半个月的敏捷开发培训。一方面,我们要感谢敏捷开发对项目实施带来的便利,没有臃肿的功能设计审核流程,也没有各种瀑布开发模型下的交付文档,从需求到最后的开发落地,差不多在两三天内就可以完成;另一方面,我们也要面对敏捷开发最终带给我们的挑战,由于需求讲解的不清楚,需求没有长远的规划考虑,最终导致后面不得不重新开发返工。我们项目的敏捷开发实施,以一个迭代为标志,一个迭代大概两周时间,分四个步骤:一是迭代故事梳理会,迭代开始前,由业务人员进行需求讲解,我们将需求分解成一个一个的故事卡片,贴在墙上;二是任务分解,针对每一个故事卡,需要完成哪些开发,哪些子系统的哪些模块涉及到开发,各自模块到负责人将任务卡片贴到故事卡下面,并分析评估完成该项工作需要花费多少时间;三是测试确认,测试人员针对故事进行测试案例编写,每个故事卡需要测试的功能点,贴在每张故事卡点下面,项目组成员对本次迭代的工作量和功能点进行最终确认;四是迭代总结,确认完成后进入开发阶段,开发验收完成后,迭代的最后一天,进行迭代验收和总结会议,总结本次迭代的完成情况,不能完成的功能点,延后到下个迭代进行。

通过这次敏捷项目的实战,最大的启发是:在系统设计的初期,需要站在战略性编程的高度去思考系统的设计和搭建,在系统设计初期阶段就需要意识到,光有运行的代码是不够的,最主要的目标应该是有一个不仅能够运行还能解决问题的系统,并且整个团队整个项目的参与人员能够充分理解系统设计的目的和最终需要达到的效果。在这次敏捷项目中,我们采用了滚动设计的方式,并没有将工作的重心放在项目初期进行详细的系统设计过程,而是随着时间的推移,对系统和需求的更多理解,进行了大量的设计改进,开发的递增也是一个抽象的过程,并没有为了满足客户一时提出的某些想法而作出某种特性的新增。最理想的情况是从设计的一开始就考虑到了未来的某种需求是需要的,更改系统设计时会带来什么样的变化,那么当完成每个需求变更时,系统运行的预期结果和预想的一样,但是这种理想是不存在的。

作为微服务平台,我们将模块细化抽象成一块块独立的微服务子系统,通过众多微服务子系统的服务输出来完成一个特别巨大的功能,在项目初期,很多人担忧,模块细化得这么多,一个功能就需要好几个系统的服务调用才能完成,对性能会不会有影响,网络延迟等都会降低系统的响应能力。从08年左右开始,伴随着硬件生产工艺的提升和硬件性能的极速增长,软件领域一直都有一个说法就是拿空间换时间的概念,我们的微服务应用都是部署在同一机房内,在千兆局域网内,系统间通信的延时完全可以依靠硬件来解决。一个复杂的系统,其jar文件的依赖,随着需求的增多,会有越来越多的依赖添加进来,那么这个系统最后会变得无比巨大,jvm启动的时候,需要加载的东西就会越来越多,应用部署和启动耗时就会越来越长。同时,在系统中,有的模块功能是基于CPU敏感型的,这样的应用将其部署在CPU多核系统中,而有的模块是内存敏感型的,将其部署在内存更充足的应用上更合适。如果这些不同的模块同属于同一个单体应用,如何性能调优,资源分配,都不能达到应用性能优化的最大化。单体应用的可靠性也是一大问题,所有的模块都运行在同一个进程中,任何某个模块的内存泄露等BUG都会造成整个服务的不可用,但是对于微服务集群模式,并不会存在这样的问题。微服务通过分解巨大单体式应用为多个服务方法解决了复杂性的问题,在功能不变的情况下,应用被分解为多个可管理的分支或服务,每个服务都有一个清晰的服务API边界。单个开发只需要关注其关注的模块。当然,这里有一个重大的理论误区,并不是说将应用拆分的越细越好,那些相互依赖实在非常紧密的服务,就应该将其归并到同一个微服务应用下面,要避免为了拆分而拆分。如果多个模块耦合严重,就把这些模块合并成一个,而判断模块的耦合,服务的依赖程度,取决于开发者对当前服务功能的理解和判断,以及对未来系统扩展和可能需要提供的服务功能的预期判断。

开发微服务应用,对于开发者个体而言,开发能力需求降低了,因为你只需要关注你自己领域内的需求和功能服务,你有充足的时间去理解和思考功能服务和小应用的服务设计。但微服务应用对开发者的设计能力有了新的考量,单个微服务应用的设计,从接口开始,就需要着重思考如何完成需求功能,并能提供服务。考验设计的能力从模块接口API开始,一个微服务模块应用,最好的是有一个简单的接口,但是在简单的接口下面,是一个深思熟虑之后的代码实现,而不是一个简单的实现。举个例子,有一个订单服务的应用,该应用需要完成订单的整个生命周期管理,下单、取消、查询等等。有的开发者,一上来就设计一个很大的接口,通过枚举值来进行if else判断是下单请求、取消请求、查询请求,甚至下单时间这样的字段都需要在接口中定义由外部请求传入,这样的接口我认为就是一个非常失败的接口设计,不但违背了软件设计的单一职责约束,更是埋下隐患,如果未来需求提出需要一个功能,订单确认需要进行是否超时的判断,怎么办?因此,每一个微服务的应用,需要有简单的接口,而不是一个简单的CRUD服务。接口本身应该是非常简洁的,功能明确,字段足够,把复杂的功能隐藏在简洁接口的下边,这些知识不应该出现在它的界面中,这才是一种不错的抽象。对于架构师而言,需要站在整个系统层面来度量所有微服务的API,界定好每个服务的职责边界,最好的设计不是第一个设计,而是设计两次,采用完全不同的方法来实现,做一个评判,演示一下实际的效果。我认为,微服务、领域驱动设计、敏捷开发,三者是一个完美的搭档配合。通过遵循领域驱动设计的架构原则将应用功能分解成独立的最小权限原则的服务,将同一个领域内的问题集中在同一微服务应用内,以敏捷开发快速迭代的方式实现功能的快速开发和集成。

对于微服务和敏捷开发而言,是一把双刃剑,使用得好,它是你手中的利器,披荆斩棘,能解决绝大部分问题,使用不好,它就是刺向你自己的长矛,千疮百孔。如果尝试使用微服务开发或者重构产品应用时,一定要理清一个问题,你的组织和团队是否已准备好过渡到微服务,各方面的保障是否已经就绪,相应的绩效考核,甚至开发环境是否已有保障。在项目初期的头一个月,因为一直担忧能不能依靠微服务将此项目做下来,产生去掉微服务,走回传统的单一整体式应用程序的想法。为此,参与微服务系统开发时,我们根据不同的领域子系统将项目组划分成单个的小团队,每个小团队都必须是高绩效的,整个系统将由一系列的独立服务构成,各个独立服务负责提供特定的服务,每个小团队试图解决其各自领域下的业务问题,必须依靠非常强大的执行力,才能在承诺的时间内提供服务保障,有效推动项目的进度。其次,团队必须要花费时间和精力去学习新的开发工具。在这次项目实施过程中,我们项目引入了maven,Git等很基本开发的工具,但是团队成员之前参与的都是单体式应用开发,使用的是svn等版本管理工具,花费了许多的时间和精力去学习这两款工具。

最后,再强调一点,微服务下的服务治理。当一个项目变得庞大之后,服务治理框架会变得尤为重要,服务生命周期管理,服务上下线随意,线上服务鱼龙混杂,服务变得上线容易下线难,服务上线前的审批流程,测试发布流程和服务下线通知机制需要通过服务治理平台进行规范化。服务的容量规划,随着业务的发展,服务调用量越来越大,服务的容量问题就会逐渐暴露出来,什么时候加机器,加几台,需要什么样的配置,这些问题我们项目组现有的解决方案还是采用性能压力测试,测试出来一个基准值,然后通过运维人员进行人工干预,在未来的规划中,我们希望通过采集服务的调用性能、时延、成功率、系统资源占用等综合指标,通过历史数据比对分析,识别服务容量瓶劲,对采集的数据进行综合计算,得出单核CPU能够支持的服务调用量,实现智能化运维,服务可以动态扩展,也即在线动态服务治理能力,服务安全也是一个非常重要的问题,我们项目现阶段,服务安全是没有任何保障的,我们基于zookeeper集群做的服务发现,虽然对zk做了密码防护措施,仍然未达到生产级的服务安全保护。安全测试人员认为,如果攻击方获得了zk的用户名和密码,那么他便可以不经授权就访问到系统内到所有服务了。

微服务模式下,需要做的事情还有很多,以后再和大家分享一下我们在服务治理,日志查询方面所做的尝试方案。

原文  http://rdc.hundsun.com/portal/article/947.html
正文到此结束
Loading...