想必你已知道了微服务及其工做原理,如今是时候探讨如向微服务转变这个关键话题了。数据库
为何要向微服务转变编程
总体式(monolithic)应用程序很庞大(代码行数方面)、很复杂(功能依赖和数据等方面),为跨地区的成千上万用户提供服务,须要多个开发人员和 IT 工程师。浏览器
总体式应用程序可能相似下图:安全
图 1:总体式应用程序的基本结构服务器
有时,即便具备全部这些特色,应用程序最初也可能顺畅运行,可能在应用程序可扩展性或性能方面不会遇到挑战。但用着用着会出现问题,问题因应用程序而异。架构
好比对于云或 Web 应用程序而言,因为更多用户使用服务,你可能遇到可扩展性问题,或者因为更长的构建时间和回归测试,按期发布新的更新可能变得成本高、难度大。并发
如图 2 所示,总体式应用程序的用户或开发人员可能遇到右边列出的一个或多个问题。负载均衡
图 2:总体式应用程序的潜在问题dom
这时迁移到微服务可能听起来不只仅是时髦的想法,更像是大救星。应用程序的迁移会相似图 3 所示:异步
图 3:从总体式应用程序向微服务转变
那么,如何进行这种转变?有两种可能的场景:
后一种场景的可能性大得多,但不管目前的状况如何,都有必要了解这两种场景的前因后果。
使用微服务建立新应用程序
我尚未看到不少从头开始构建基于微服务的应用程序的真实场景。一般,应用程序已部署到位,我搞过的大多数应用程序更可能是从总体式架构向微服务架构转变。
在这种状况下,架构师和开发人员的意图一直是重用一些现有的实现。但因为技能在市场上很是广泛、一些成功的实现发布,咱们会看到从头开始构建基于微服务的应用程序的更多例子,所以固然有必要探究这种场景。
假设你已摸清了全部需求,准备好处理要构建的应用程序的架构设计。你在入手时须要考虑许多常见的最佳实践,这些实践在下面各节中有介绍。
组织准备
你要问本身的第一个问题是,贵组织是否准备好向微服务转变。
这意味着贵组织的各个部门如今须要从如下方面对软件的构建和发布进行不一样的思考:
如图 3 所示,新系统将包含一组独立服务,每一个服务负责提供特定服务。这是微服务模式的一大优点:减小了通讯开销,包括多场不间断会议。
团队应按照所要解决的业务问题或领域加以组织。而后,沟通变为敲定要遵循的一套标准/协议,那样这些微服务就能彼此协做。
这须要投入大量资本,致力于招聘拥有新技能的人员,并从新培训现有工做人员。从长远来看,若是采用微服务的决定是正确的,组织会看到成本节省,于是收回投入。
基于服务的方法
与总体式应用程序不一样,如果微服务,你须要采用自我维持的基于服务的方法。
应用程序比如是一组松散耦合的服务,这些服务相互通讯以提供完整的应用程序功能。
应将每项服务视为有其生命周期的独立服务,可由独立团队开发和维护。这些团队要从各类技术中进行选择,包括最适合其服务要求的语言或数据库。
好比针对电子商务站点,团队要编写一个彻底独立的使用内存数据库的服务,好比购物车微服务,以及使用关系数据库的另外一项服务,好比订购微服务。
实际应用程序可能将微服务用于基本功能,好比身份验证、账户、用户注册和通知,业务逻辑封装在 API 网关中,API 网关基于客户端和外部请求调用这些微服务。
提醒一下:微服务多是一个开发人员实现的小服务,也多是须要多个开发人员的复杂服务。就微服务而言,大小可有可无;它彻底依赖服务要提供的一项功能。
此时必须考虑的其余方面是扩展、性能和安全。扩展要求可能不同,应在每一个微服务层面根据须要来提供。应在全部层面考虑安全,包括静态数据、进程间通讯和传输中数据等。
进程间(服务到服务)通讯
必须考虑的关键方面是安全和通讯协议。异步通讯是最佳选择,由于它可确保全部请求正常运行,不会长时间占用资源。
使用 RabbitMQ 等消息总线可能有利于这种通讯。它很简单,能够扩展到每秒数十万条消息。
为防止消息传递系统在发生故障后成为单一故障点,必须正确设计消息传递总线以实现高可用性。其余选项包括另外一种轻量级消息传递平台 ActiveMQ。
安全是该阶段的关键。除了选择正确的通讯协议外,可以使用 AppDynamics 之类的行业标准工具来监控和衡量进程间通讯。须自动向安全团队报告任何异常状况。
如有数千个微服务,处理一切确实变得复杂起来。后面会解释如何借助发现服务和 API 网关解决此类问题。
技术选择
向微服务转变的最大优点是让你能够选择。每一个团队能够独立选择最适合特定微服务的语言、技术和数据库等。
若采用总体式方法,团队一般没有这样的灵活性,所以确保你没有忽视并错过该机会。
即便团队在处理多个微服务,也要将每一个微服务视为独立的服务并进行分析。
为每一个微服务选择技术时,必须牢记可扩展性、部署、构建时间、集成和插件可操做性等。
若是是数据较少但访问较快的微服务,内存数据库可能最合适,而其余微服务可能使用一样的关系数据库或 NoSQL 数据库。
实现
实现是关键阶段,这时候全部培训和最佳实践知识派得上用场。
要记住的几个关键方面包括:
它有助于代码审查等各个方面,便于在一个地方访问全部代码。长远来看,有必要对全部服务实行一样的源代码控制。
那样,能够根据须要集成代码,大多天天进行。有几种工具可用,不过 Jenkins 普遍使用。Jenkins 是一种开源工具,有助于软件构建和发布过程实现自动化,包括持续集成和持续交付(CI/CD)。
这包括管理服务响应时间(超时)、处理下游服务的 API 更改以及限制自动重试次数。
使用微服务时,别惧怕经过使用复制粘贴来重用代码,但这么作要有限制。
这可能致使代码重复,但这赛过使用最终耦合服务的共享代码。微服务中,你须要的是去耦,不是紧耦合。
好比说,你将编写代码以使用服务的输出响应。每次从任何客户端调用相同的服务时,你能够复制此代码。
重用代码的另外一种方法是建立公共库。多个客户端可使用相同的库,但随后每一个客户端应负责维护其库。
若是你建立太多的库,每一个客户端维护不一样的版本,有时变得困难重重。这种状况下,你要包含相同库的多个版本,因为向后兼容性和相似问题,构建过程可能变得困难。
只要你能够控制客户端的库和版本数量,并对它们实行严格的流程,能够采用任何一种方式,这就看你的须要了。这确定有助于避免大量的代码重复。
鉴于微服务数量庞大,调试问题可能会变得困难,所以你须要在此阶段进行某种检测。
最佳实践之一是使用惟一的请求 ID 标记每一个请求,并记录每一个请求。这个惟一的 ID 标识始发请求,应由每一个服务传递给任何下游请求。
看到问题后,你能够经过日志清楚地回溯并找出有问题的服务。若是你创建集中式日志记录系统,该解决方案最有效。
全部服务都应以标准化格式将全部消息记录到此共享系统,以便团队能够根据须要从一个地方(从基础设施到应用程序)重放事件。用于集中式日志的共享库值得研究。
市面上有几种很理想的日志管理和聚合工具,好比 ELK(Elasticsearch、Logstas和Kibana)以及 Splunk。
部署
自动化是部署过程当中的关键。没有它,微服务模式几乎不可能成功。可能有成百上千的微服务,对于敏捷交付而言,自动化必不可少。
设想部署数千个微服务并维护。其中一个微服务发生故障后会发生什么?怎么知道哪台机器有足够的资源来运行你的微服务?
若没有落实自动化,应对这种状况变得很是复杂。Kubernetes 和 Docker Swarm 等各类工具可用于自动化部署过程。
操做
整个过程的操做部分也须要自动化。这里谈论的一样是成百上千的微服务,组织能力须要足够成熟才能处理这种复杂程度。
你须要一个支持系统,包括如下方面:
但在规模化环境中,这也须要实现自动化。只需设置一个整数值,告诉想要为特定微服务运行的实例数量。
它可使用 API 网关和发现服务来完成任务,你能够针对每种设备类型(好比移动设备或浏览器)或用例使用一台边缘服务器。Netflix 开发的一款开源应用软件 Zuul 可用于此功能及其余功能。
指定时间事后,应进行另外一次尝试,依此类推。一旦响应成功,从新链接电路。这应该在服务实例层面进行。Netflix 的 Hystrix 提供了开源断路器实现。
将总体式应用程序迁移到微服务
虽然构建基于微服务的新应用程序的大多数最佳实践也适用于迁离现有的总体式应用程序,但若是遵循另一些准则,可以使迁移更简单、更高效。
虽然将整个总体式应用程序转换成彻底基于微服务的应用程序听起来可能很正确,但将每项功能转换成微服务可能并不高效,在一些状况下可能成本很高。
毕竟,你到头来要从头开始编写应用程序。正确的迁移方式可能须要逐步进行,如图 4 所示:
图 4:基本的迁移步骤,从总体式应用程序到微服务
下一个问题是:目前的总体式应用程序从何处入手?若是应用程序确实很旧,进行分解很耗时、难度大,从头开始可能更好。
在能够快速禁用部分代码、技术架构并不彻底过期的其余状况下,最好先将组件从新构建为微服务,并换掉旧代码。
微服务标准
那么问题变成了哪些组件应该先迁移或甚至要不要迁移。这让我想到了所谓的“微服务标准”,这概述了选择应迁移到微服务的功能并肯定优先级的可行方法之一。
它们是你制定的一套规则,根据组织当时的要求,决定将现有总体式应用程序的组件转换成微服务是否适合。
这时机在这里很重要,由于组织的要求可能不断变化,你可能要回过头来,将更多组件转换成微服务。
换句话说,因为要求变化,总体式应用程序的额外组件可能适合转换。如下是转换过程当中被视为微服务标准的几个最佳实践:
①你须要肯定哪些功能频繁使用
先将频繁使用的服务或应用程序功能转换成微服务。记住:微服务只执行一个明肯定义的服务。牢记这个原则,相应地划分应用程序。
②可能存在性能不佳的组件,其余替代方案随时可用
可能有开源插件,或者你可能想从头开始构建服务。应牢记的要点之一是微服务的边界。
只要你设计的微服务只作一件事,就很好。肯定边界经常很难,你会发现实践一下会更容易。
查看微服务边界的另外一种方法是,应该几周内就能重写整个微服务,而不是花几个月来重写服务。
③更好的技术替代方案或多语言编程
针对特定领域的语言可用于帮助解决问题域(problem domain)。这尤为适用于过去你收到许多改进请求,预计未来会继续如此的组件。
若是你不只认为可使用市面上的新语言或功能简化这种组件的实现,未来的维护和更新还会变得更容易,如今正是应对这种变化的时候。
在其余状况下,你可能发现另外一种语言提供的并发抽象比目前使用的语言更容易。
能够将新语言用于特定的微服务,而应用程序的其他部分仍然使用不一样的语言。
一样,你可能但愿一些微服务很是快,可能决定用 C 语言编写以得到最大效益,而不是用另外一种高级语言编写。说究竟是要利用这种灵活性。
④存储替代方案或多语言持久性
大数据大行其道,若是使用 NoSQL 数据库而不是关系数据库,应用程序的一些组件可能会提供价值。
若是应用程序中的任何此类组件可得益于该替代方案,可能正是改用 NoSQL 的时候。
这些是你应该为总体式应用程序中的每一个服务或功能而考虑的关键方面,你须要先注重这几项的转换。一旦你从高优先级的部分得到了价值,随后能够运用其余规则。
⑤修改请求
任何软件生命周期中要跟踪的一个重要方面是新的改进请求或更改。因为构建和部署时间,更改请求数量更多的功能可能适用于微服务。
分离这类服务能够缩短构建和部署时间,由于你没必要构建整个应用程序,只需更改微服务,这还能够为应用程序的其他部分提升可用性时间。
⑥应用程序的某些部分老是增长部署的复杂性
在总体式应用程序中,即便某项功能未加变更,你仍得完成整个构建和部署过程。
若是存在这种状况,划分这些组件并用微服务取代大有助益,这样能够为总体式应用程序的其他部分缩短总的部署时间。
⑦辅助服务
在大多数应用程序中,核心或主要的服务依赖一些辅助服务。没有这类辅助功能,可能会影响核心服务的可用性。
好比在求助台应用程序中,工单依赖产品目录服务。若是产品目录服务不可用,用户没法提交工单。
若是存在这种状况,应将辅助服务转换成微服务,并确保高可用性,以便它们能够更好地服务于核心服务。(这些又叫断路器服务。)
视应用程序而定,这些标准可能须要将大多数服务转换成微服务,目的是简化转换过程,那样你能够肯定优先级,并为迁移到基于微服务的架构制定路线图。
为服务从新设计架构
一旦肯定了要迁移的转换成微服务的功能,能够遵循前面所述的最佳实践,开始为已选择的服务从新设计架构。
如下是须要牢记的几个方面:
考虑现有功能使用的数据,或针对微服务相应地建立和规划数据策略。若是该功能在 Oracle 之类的密集数据库上,迁移到 MySQL 是否有意义?
肯定你将如何管理数据关系。最后,将每一个微服务做为单独的应用程序来运行。
目的在于除非须要,不然不添加新功能,而是从新打包现有代码并公开所需的 API。
这让你有机会测试和关注性能。一旦有信心,你能够将全部流量迁移到微服务,禁用或删除旧代码。
这意味着你可能在生产环境中运行相同微服务的两个或更多版本。一些用户流量能够路由到新的微服务版本,确保服务正常运行、性能良好。
若是新版本未在最佳状态下运行,很容易将全部流量回滚到先前版本,并将新版本退回给开发团队。这里的关键是创建可重复的自动化部署流程,竭力实现持续交付。
微服务的混合方法
开发人员编写全新的应用程序时,能够直接遵循微服务架构原则和蓝图来构建应用软件。开发人员有时遵循微服务和总体式应用程序的混合方法。
在这种状况下,他们能够将应用程序的部分组件开发成微服务,其他部分基于某些标准遵循标准的 SOA/MVC 实践。
其想法是,并不是应用程序的全部组件均可以转换成微服务。微服务提供了很大的灵活性,但这种灵活性要付出一些代价。
混合方法旨在兼顾灵活性和成本这两方面,之后能够根据须要从总体式应用程序获取组件、转换成微服务。关键是在这个转变期间牢记这两种方法以及微服务标准。
感兴趣的能够本身来个人Java架构群,能够获取免费的学习资料,群号:855801563对Java技术,架构技术感兴趣的同窗,欢迎加群,一块儿学习,相互讨论。