随着公司国际化战略的推行以及本土业务的高速发展,后台支撑系统已经不堪重负。在吞吐量、稳定性以及可扩展性上都没法知足日益增加的业务需求。对于每10万元额度的合同,从销售团队准备材料、与客户签单、递交给合同部门,再到合同生效大概须要3.5人天。随着业务量的快速增加,签定合同的成本急剧增长。 php
合同管理系统是后台支撑系统中重要的一部分。当前的合同系统是5年前使用.NET基于SAGE CRM二次开发的产品。 一方面,系统架构过于陈旧,性能、可靠性没法知足现有的需求。另外一方面,功能繁杂,结构混乱,定制的代码与SAGE CRM系统耦合度极高。因为是遗留系统,熟悉该代码的人早已离职多时,新团队对其望而却步,只能作些周边的修补工做。同时,还要承担着边补测试,边整理逻辑的工做。 html
在没法中断业务处理的状况下,为了解决当前面临的问题,团队制定了以下的策略: ios
1). 在现有合同管理系统的外围,构建功能服务接口,将系统核心的功能分离出来。 git
2). 利用这些功能服务接口做为代理,解耦原合同系统与其调用者之间的依赖; github
3). 经过不断构建功能服务接口,逐渐将原有系统分解成多个独立的服务。 web
4). 摒弃原有的合同管理系统,使用全新构建的(微)服务接口替代。 数据库
多年来,咱们一直在技术的浪潮中不断乘风破浪,扬帆奋进,寻找更好的方式构建IT系统。微服务架构(Micro Service Architect)是近一段时间在软件体系架构领域里出现的一个新名词。它经过将功能分解到多个独立的服务,以实现对解决方案或者复杂系统的解耦。 apache
微服务的诞生并不是偶然: 领域驱动设计指导咱们如何分析并模型化复杂的业务;敏捷方法论帮助咱们消除浪费,快速反馈;持续交付促使咱们构建更快、更可靠、更频繁的软件部署和交付能力;虚拟化和基础设施自动化( Infrastructure As Code)则帮助咱们简化环境的建立、安装;DevOps文化的流行以及特性团队的出现,使得小团队更加全功能化。这些都是推进微服务诞生的重要因素。 编程
实际上,微服务自己并无一个严格的定义。不过从业界的讨论来看,微服务一般有以下几个特征: 浏览器
每一个服务都是很小的应用,至于有多小,是一个很是有趣的话题。有人喜欢100行之内,有人同意1000行之内。数字并非最重要的。仁者见仁,智者见智,只要团队以为合适就好。只关注一个业务功能,这一点和咱们日常谈论的面向对象原则中的”单一职责原则”相似,每一个服务只作一件事情,而且把它作好。
每一个服务都运行在一个独立的操做系统进程中,这意味着不一样的服务能被部署到不一样的主机上。
服务和服务之间经过轻量级的机制实现彼此间的通讯。所谓轻量级通讯机制,一般指基于语言无关、平台无关的这类协议,例如XML、JSON,而不是传统咱们熟知的Java RMI或者.Net Remoting等。
不须要改变依赖,只更改当前服务自己,就能够独立部署。这意味着该服务和其余服务之间在部署和运行上呈现相互独立的状态。
综上所述,微服务架构采用多个服务间互相协做的方式构建传统应用。每一个服务独立运行在不一样的进程中,服务与服务之间经过轻量的通信机制交互,而且每一个服务能够经过自动化部署方式独立部署。
相比传统的单块架构系统(monolithic),微服务在以下诸多方面有着显著的优点:
问题有其具体性,解决方案也应有其针对性。用最适合的技术方案去解决具体的问题,每每会事半功倍。传统的单块架构系统倾向采用统一的技术平台或方案来解决全部问题。而微服务的异构性,能够针对不一样的业务特征选择不一样的技术方案,有针对性的解决具体的业务问题。
对于单块架构的系统,初始的技术选型严重限制未来采用不一样语言或框架的能力。若是想尝试新的编程语言或者框架,没有完备的功能测试集,很难平滑的完成替换,并且系统规模越大,风险越高。基于微服务架构,使咱们更容易在遗留系统上尝试新的技术或解决方案。譬如说,能够先挑选风险最小的服务做为尝试,快速获得反馈后再决定是否试用于其余服务。这也意味着,即使对一项新技术的尝试失败,也能够抛弃这个方案,并不会对整个产品带来风险。
该图引用自Martin Fowler的Microservices一文
单块架构系统运行在一个进程中,所以系统中任何程序的改变,都须要对整个系统从新测试并部署。 而对于微服务架构而言,不一样服务之间的打包、测试或者部署等,与其它服务都是彻底独立的。对某个服务所作的改动,只须要关注该服务自己。从这个角度来讲,使用微服务后,代码修改、测试、打包以及部署的成本和风险都比单块架构系统下降不少。
单块架构系统因为单进程的局限性,水平扩展时只能基于整个系统进行扩展,没法针对某一个功能模块按需扩展。 而服务架构则能够完美地解决伸缩性的扩展问题。系统能够根据须要,实施细粒度的自由扩展。
微服务架构同时也能提高故障的隔离性。例如,若是某个服务的内存泄露,只会影响本身,其余服务可以继续正常地工做。与之造成对比的是,单块架构中若是有一个不合格的组件发生异常,有可能会拖垮整个系统。
康威定律(Conway’s law)指出:一个组织的设计成果,其结构每每对应于这个组织中的沟通结构(organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations)。传统的开发模式在分工时每每以技术为单位,好比UI团队、服务端团队和数据库团队,这样的分工可能会致使任何功能上的改变都须要跨团队沟通和协调。而微服务则倡导围绕服务来分工,团队须要具有服务设计、开发、测试到部署所需的全部技能。
随着团队对业务的理解加深和对微服务实践的尝试,数个微服务程序已经成功构建出来。不过,问题同时也出现了:对于这些不一样的微服务程序而言,虽然具体实现的代码细节不一样,但其结构、开发方式、持续集成环境、测试策略、部署机制以及监控和告警等,都有着相似的实现方式。那么如何知足DRY原则并消除浪费呢?带着这个问题,通过团队的努力,Stencil诞生了。 Stencil是一个帮助快速构建Ruby微服务应用的开发框架,主要包括四部分:Stencil模板、代码生成工具,持续集成模板以及一键部署工具。
Stencil模板是一个独立的Ruby代码工程库,主要包括代码模板以及一组配置文件模板。
代码模板使用Webmachine做为Web框架,RESTful和JSON构建服务之间的通讯方式,RSpec做为测试框架。同时,代码模板还定义了一组Rake任务,譬如运行测试,查看测试报告,将当前的微服务生成RPM包,使用Koji给RPM包打标签等。
除此以外,该模板也提供了一组通用的URL,帮助使用者查看微服务的当前版本、配置信息以及检测该微服务程序是否健康运行等。
[ { rel: "index", path: "/diagnostic/" }, { rel: "version", path: "/diagnostic/version" }, { rel: "config", path: "/diagnostic/config" }, { rel: "hostname", path: "/diagnostic/hostname" }, { rel: "heartbeat", path: "/diagnostic/status/heartbeat" }, { rel: "nagios", path: "/diagnostic/status/nagios" } ]
配置文件模板主要包括NewRelic配置,Passenger配置、Nagios配置、Apache配置以及Splunk配置。经过定义这些配置文件模板,当把新的微服务程序部署到验收环境或者产品环境时,咱们马上就可使用Nagios、NewRelic以及Splunk等第三方服务提供的功能,帮助咱们有效的监控微服务,并在超过初始阈值时得到告警。
借助Stencil代码生成工具,咱们能在很短期内就构建出一个能够当即运行的微服务应用程序。随着系统愈来愈复杂,微服务程序的不断增多,Stencil模板和代码生成工具帮助咱们大大简化了建立微服务的流程,让开发人员更关注如何实现业务逻辑并快速验证。
Create a project from the stencil template (version 0.1.27) --name, -n <s>: New project name. eg. things-and-stuff --git-owner, -g <s>: Git owner (default: which team or owner) --database, -d: Include database connection code --triggered-task, -t: Include triggered task code --provider, -p: Is it a service provider? (other services use this service) --consumer, -c: Is it a service consumer? (it uses other services) --branch, -b <s>: Specify a particular branch of Stencil --face-palm, -f: Overide name validation --help, -h: Show this message
如上代码所示,经过指定不一样参数,咱们能建立具备数据库访问能力的微服务程序,或者是包含异步队列处理的微服务程序。同时,咱们也能够标记该服务是数据消费者仍是数据生产者,能帮助咱们理解多个微服务之间的联系。
基于持续集成服务器Bamboo,团队建立了针对Stencil的持续集成模板工程,并定义了三个主要阶段:
利用持续集成模板工程,团队仅需花费不多的时间,就能够针对新建的微应用程序,在Bamboo上快速定义其对应的持续集成环境。
全部的微服务程序都部署并运行在亚马逊AWS云环境上。同时,咱们使用Asgard对AWS云环境中的资源进行建立、部署和管理。 Asgard是一套功能强大的基于Web的AWS云部署和管理工具,由Netflix采用Groovy on Grails开发,其主要优势有:
因为Asgard对RESTful的良好支持,团队实现了一套基于Asgard的命令行部署工具,只需以下一条命令,提供应用程序的名称以及版本号,就可自动完成资源的建立、部署、流量切换、删除旧的应用等操做。
asgard-deploy [AppName] [AppVersion]
同时,基于命令行的部署工具,也能够很容易的将自动化部署集成到Bamboo持续集成环境。
经过使用微服务框架Stencil,大大缩短了团队开发微服务的周期。同时,基于Stencil,咱们定义了一套团队内部的开发流程,帮助团队的每一位成员理解并快速构建微服务。
通过5个月的努力,咱们从新构建了合同管理系统,将以前的产品、价格、销售人员、合同签署、合同审查以及PDF生成都定义成了独立的服务接口。相比以前大而全、难以维护的合同管理系统而言,新的系统由不一样功能的微服务组成,每一个微服务程序只关注单一的功能。每一个微服务应用都有相关的负责人,经过使用Page Duty创建消息通知机制。每当有监控出现告警的时候,责任人能当即收到消息并快速作出响应。
因为微服务具备高内聚,低耦合的特色,每一个应用都是一个独立的个体。当出现问题时,很容易定位问题并解决问题,大大缩短了修复缺陷的周期。另外,经过使用不一样功能的微服务接口提供数据,用户接口(UI)部分变成了一个很是简洁、轻量级的应用,更关注如何渲染页面以及表单提交等交互功能。
经过使用微服务架构,在不影响现有业务运转的状况下,咱们有效的将遗留的大系统逐渐分解成不一样功能的微服务接口。同时,经过Stencil微服务开发框架,咱们可以快速地构建不一样功能的微服务接口,并能方便地将其部署到验收环境或者产品环境。最后,得益于微服务架构的灵活性以及扩展性,使得咱们可以快速构建低耦合、易扩展、易伸缩性的应用系统。