如何从传统单体架构转向微服务

当今,把单体架构的应用拆成微型服务是很时髦的。让我想起了2000年世纪初的那些日子,那时SOA正在流行,大多数公司,供应商和系统集成商,正忙着挥动SOA魔杖,希望它能将他们的遗留应用程序转变为更加灵活和敏捷的SOA应用程序。一个供应商甚至说,“使用SOA,您不需要编写一行代码“。不幸的是,事实却根本不是这样。虽然他们的大肆宣传,努力去做,结果却不美好。虽然服务的概念还不错,但是SOA具有强类型的服务定义,并且在HTTP上使用SOAP非常麻烦。这些缺点似于谚语中所说的“当你有一个新的闪亮的锤子时,一切看起来都像钉子”,这就是SOA的末日。

几年前,我开始着手一个项目,创建一个框架,以帮助构建面向过程的应用程序,并使其更加轻松和敏捷。经过深思熟虑,我选择Java EE作为构建框架的选择平台,考虑到Java EE7所提供的许多优秀特性,这是当时的最新版本。

最初的系统框架是根据Java EE最佳实践设计的。具有逻辑分层结构的框架使用了MVC架构模式,使用依赖注入来减少耦合和提高灵活性。最后的部署由几个JAR和WAR组件组成,它们封装在EAR应用程序中,如下所示。

随着框架开始正式使用,增加了更多的功能。

尽管应用程序开发中使用了大多数最佳实践,但我最终发现整个应用程序开始变得笨拙,以至于修复、构建和部署的每个周期都花费很长时间。使得转向到基于微服务的架构的诱惑力太大了。尽管如此,我还是没有想到贸然拆分这个庞大的应用系统,以免破坏任何现有的功能。直到最后,我才意识到我已经陷得太深了。我别无选择,只能停止并重新考虑通过创建更小的可管理的微服务来重构整个应用程序。

还有其他几个原因迫使我去做:

许多函数可以使用更合适的技术来实现,NodeJS和Spring Boot也有一些。

在应用程序中的功能进行更改时,模块之间紧密耦合,灵活性不足。

在云部署的时候单体体系架构存在伸缩性问题

通过微服务体系结构,应用程序被建模为独立的业务模块或功能——不多也不少。遵循微服务的基本原则,并将单体架构应用程序划分为更小的功能独立模块,从而产生多个功能模块,其中包含表示、业务和持久层,它们位于独立的进程中。

从整体到微服务的典型过渡如下图所示:

一般来说,使用微服务开发应用程序有两种方法:

直接使用microservices体系架构开发一个新的应用程序。

从一个现有单体架构应用开始,然后逐渐拆分功能模块并迁移到微服务架构中。

虽然这两种方式都有赞成和反对的理由,但我倾向于赞同后者,理由如下:

从头开始建立微服务的基础基础设施非常耗时。

在初始阶段,在现有系统中分模块一个一个的实现用例是最快的。。

随着单体系统的规模不断扩大,完整应用程序的整体功能图更加清晰,可以很容易地识别出潜在微服务的功能边界。

一个设计良好的单体架构应用程序可以通过最少的工作量被分解为微服务。

所以,当我终于决定拆分单体应用系统到微服务架构时,很是安心。要注意Martin Fowler的论点策略第一条:“从开始你就应该构建一个新的应用程序作为一个单体架构应用,即使你认为它很可能将受益于一个microservices架构。这是正确的,因为拆分一个功能并不是那么困难,尤其如果是当它最初被设计好的时候。他进一步提到:“允许您探索系统及其组件边界的复杂性”,并“随着您对边界的了解和服务管理的增加,继续提供服务”。

当您的单体架构应用程序已变得非常复杂,以至于开发和维护工作以及运行时性能都受到影响时,您才能开始收获微服务架构的好处。由于分布式架构在开发和运行中花费都超过了好处,所以微服务体系结构并不能使较小的应用程序受益。

下图显示了重构后的系统的微服务架构

那么,微服务应该设计得有多大呢?没有绝对的答案。它是高度主观的,取决于您的具体实际用例。然而,你可以参考微服务的一个关键原则——做一件事,并做好它。基于业务上下文的模块化应用程序的领域驱动设计方法是将大型系统分解为较小的微服务的理想方法。

接下来,我将在过渡到微服务体系结构的过程中详细介绍我的经验。

可伸缩性

回想一下,在逻辑分层的情况下,作为一个单独的进程部署的传统分层架构应用,尽管执行良好,但由于组件的负载不平衡,其伸缩性并不十分有效。通过将表示层、业务层和持久层分布到单独的进程空间,并使用RPC (REST、web服务等)进行通信,在这种情况下,一个主要的缺点是,它导致了几个远程调用开销,用于访问单个功能。相反,使用微服务方法,每个服务或功能与同一进程空间中的所有层,都可以独立地部署和伸缩。

微服务架构应用一个优点是能够利用 Docker, Kubernetes or Mesosr等技术提供灵活地移动单个服务跨多个环境(开发、测试和生产),避免配置方面的问题,而更重要的是,根据资源的利用率,为应用程序提供特定功能。

服务发现

对于微服务,一个重要的需求是能够动态发现和访问服务,从而真正地解耦和隔离它们。从技术上讲,这意味着在客户机服务中不需要硬编码服务端点。Eureka是实现服务注册的几种选择之一,它支持注册、存储和查询关于服务的元数据。

负载平衡

随着微服务体系结构中服务的激增,以及需要对需求进行横向扩展,一种健壮的机制来平衡一组冗余服务之间的负载是至关重要的。用它的可插入的负载平衡规则,集成到服务注册中心和内置的故障恢复能力。

Ribbon,加上Eureka提供了一个出色的解决方案,提供高度解耦和可伸缩的系统。

Reactive Systems(反应性系统)

主要依赖于同步交互作用的单体架构应用受到了有限的灵活性和弹性的影响。另一方面,新的微服务被设计成使用反应性编程范式的Vertx集群应用程序。这些微服务通过消息传递基础设施与其他服务协作,提高了响应能力和时间和空间上的解耦系统。这些实践提供了反应性系统的迫切需要——响应性、弹性、弹性和消息驱动。

持久性

将单体多层架构应用数据模型分解为本地到每个服务的自治数据模型确实是一个挑战。原始数据模型由多个模式组成,其中包含相当多的表,其中有大量的连接。通过本地事务维护数据的事务完整性非常容易。

在没有连接的情况下,将单体架构数据模型拆分为功能独立的域,这本身就很乏味,但更令人生畏的是,可以跨服务同步数据,并让它们始终如一地工作,并保持完整性。采用“Saga” 模式来确保跨服务的数据的事务完整性,生产者和消费者通过事件总线进行事件协作。虽然与每个微服务有关的数据在本地持续存在,但微服务之外的数据仍然通过发送适当的事件来保存,这些事件由相关的服务消费。如果在下游持久化数据时出现错误,就会触发事件来运行补偿操作,从而沿着链向上级联。

为了保持服务的持久数据私有,采用了schema-per-service 模式。但是,各种模式共享在集群模式下运行的物理数据库。微服务数据模型的另一个挑战是查询跨服务的数据,微服务体系应用需要从各自的服务中查询单个数据源,并组合它们以生成最终的查询结果。

API网关

在单体架构中,facade模式通常用于从多个服务中提取本地数据,以服务于web层的粗粒度请求。然而,在一个微服务体系结构中,由于每个服务都要对自己的数据负责,并且生活在单独的进程空间中,所以API网关在分布式环境中充当facade,比如这个。API网关是为客户端交互提供微服务的单点入口。

在我的单体架构中,两个主要的客户端组件——客户Web应用程序和部署为WAR应用程序的员工Web应用程序通过API网关与其他微服务交互。使用其他协议的请求通过独立的API网关进行处理。

横切关注点

微服务体系结构的另一个挑战是实现横切关注点,如日志记录、安全性、审计跟踪、服务注册、服务发现、配置管理等。传统架构的应用可以使用AOP容器来很简单是实现这部分功能。而微服务架构中需要通过使用polyglot(混合持久化)技术的微服务体系结构,这些服务并不是单独为每个服务实现的,而是在微服务的底部增加额外的层来实现,使用微服务的底盘模式。

尽管在一个标准JEE应用程序中实现声明性安全性非常简单,但是在分布式安全的微服务环境中存在一些挑战。API网关作为实现安全服务的理想位置,使用JWT令牌委托授权在分布式环境中传播微服务之间的安全凭据。

流程引擎

当组织中的活动按照定义的流程自动进行时,可以很容易地使用从流程派生的度量来度量性能。这是在单体应用框架的中心引入BPMN流程引擎的主要驱动程序。顺便说一下,框架使用Camunda BPM作为流程引擎。

为了保持Camunda流程引擎独立于应用程序组件之外,有两个重要的考虑因素:

与流程服务相关的微服务被设计为Camunda流程应用程序,与相关的流程模型绑定在一起。然后独立部署的bpmn文件。

应用程序使用RESTful api与流程引擎交互。

使用集群数据库配置冗余流程引擎和持久过程数据,解决了流程引擎中单点故障的可能性。大多数服务应用程序都是使用Spring Boot实现的。

结论

虽然本文详细介绍了我的经验,从一个单体的应用程序过渡到一个基于微服务的应用程序,尽管微服务在几个领域提供了卓越的性能指标,但单体应用也不能被认为是坏的,因为它们有自己的优势。然而,我主观决定转向一个微服务体系结构。不过,我必须承认,在IDE中使用原始的单体应用框架是很酷的,特别是在整个代码库中导航,重构它们并毫不费力地生成单个部署包。所以,不要轻易试图拆分一个单体应用,除非它变得太复杂,或者你绝对感觉需要拆分它(你会知道什么时候是时候!)

作者 Simon John

原文发布于微信公众号 - 程序你好(codinghello)

原文发表时间:2018-05-24

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏java思维导图

什么是REST架构?

REST架构风格是全新的针对Web应用的开发风格,是当今世界最成功的互联网超媒体分布式系统架构,它使得人们真正理解了Http协议本来面貌。随着 REST架构成为...

1012
来自专栏小怪聊职场

求职|大学毕业如何找到一份10K+月薪的JAVA工程师工作

3455
来自专栏性能与架构

Medium 微服务策略

微服务架构的目标是帮助技术团队更快、更安全、更高质量的推动产品,服务解耦可以让团队快速迭代,对系统的影响最小。

1333
来自专栏Golang语言社区

微服务架构的优势与不足

英文原文:Introduction to Microservices   这篇文章作者是Chris Richardson,他是早期基于Java的Amazonit...

3395
来自专栏网络

资深女程序员告诉你:微服务架构如何实践?80%以上男程序员点赞

上篇文章给大家介绍了什么是微服务架构,本文将会讲到如何实践微服务。 不知道微服务架构的,可以看我上一篇文章 微服务听上去好像不错,具体怎么落地啊?这需要回答下面...

3807
来自专栏程序员的知识天地

Python自动化测试框架不知道有哪些?我都给你收集好了

随着技术的进步和自动化技术的出现,市面上出现了一些自动化测试框架,你可以使用这些框架,在调整特定测试适用性和效率参数后,测试你项目的任何模块。这节省了时间,而且...

1224
来自专栏程序你好

如何从传统单体架构转向微服务

当今,把单体架构的应用拆成微型服务是很时髦的。让我想起了2000年世纪初的那些日子,那时SOA正在流行,大多数公司,供应商和系统集成商,正忙着挥动SOA魔杖,希...

6228
来自专栏我的技术专栏

微服务的一些概念

传统的单体架构,把所有的功能都集中在一起,打包为一个war包,或者是可执行程序。部署的时候,需要部署一个完整的应用,升级时,也需要替换整个war包或是可执行程序...

1527
来自专栏ThoughtWorks

登录工程:现代Web应用的典型身份验证需求|洞见

朋友就职于某大型互联网公司。前不久,在闲聊间我问他日常工作的内容,他说他所在部门只负责一件事,即用户与登录。 ? 而他的具体工作则是为各个业务子网站提供友好的登...

3325
来自专栏CSDN技术头条

分享九款构建响应式网站的最佳PHP框架

目前,网上有大量的框架供大家选择,本文作者分享了9款各方面都兼具优势的PHP框架,主要用来构建响应式网站,开发人员可以根据自己的需求来选择下面的某一个框架。 ...

2747

扫码关注云+社区