传统SSM项目改造SpringBoot微服务实践

最近公司正准备从传统SSM项目转型微服务,笔者在其中负责了一部分改造计划。因此,本文主要总结改造过程中的思路及实践中遇到的问题。如表述不当,欢迎指正。
一.为什么要改造单体应用
1.1.什么是单体应用
传统项目一般也是单体应用,而单体应用简单来说就是一个war包中包含了该应用的所有业务功能,这样的项目就是一个单体应用。
1.2.单体应用的利弊分析
绝大多数项目都是从单体应用开始的,在初期单体应用容易部署测试,且能很好的运行。然而随着需求的增加,项目不断变得庞大,代码库也在急速膨胀,单体应用的缺点凸显:
<1>复杂度高:整个项目包含的模块非常多,模块之间的边界模糊,且互相依赖,项目十分复杂。
<2>可靠性低:一个模块出了bug,或者OOM,可能导致整个应用出现不可用,而导致严重的生产事故。
<3>可维护性差:由于项目的高复杂度,修改代码都需要经过深思熟虑,修复一个bug一个不小心就会触发另一个功能的异常,可谓刀尖上跳舞。
<4>扩展性差:整个应用只能作为一个整体去部署,而无法根据业务模块的需要进行伸缩。比如A模块访问的并发量高,需要多台机器来支撑,而B模块访问的并发量低,只需要一台机器。而由于这些模块聚集在一个war包中,因此各个模块只能在机器的数量上互相妥协。
<5>单体应用的其他弊端:影响技术创新,引入更多技术债务等
1.3.小结
基于单体应用存在的问题,势必需要对其进行改进,使其适应当前时代业务快速变化的需求,同时保证高可用性。目前,主流的思路有SOA架构和微服务体系两种,而笔者公司采用后者,因此,下文以微服务体系为例进行展示。
二.改造前的准备
在改造单体应用前,需要做好准备工作。准备工作主要包括:指定改造所要达成的目标,明确改造的影响范围,以及相应的知识储备。
2.1.制定改造所要达成的目标
如下图所示,改造后,动态密码器服务将迁移到微服务体系中,而原有单体应用对动态密码器的调用将会使用微服务体系所提供的服务。传统SSM项目改造SpringBoot微服务实践_第1张图片
2.2.明确改造的影响范围
2.2.1.改造对单体应用的影响范围

本次改造仅涉及一个基础服务:动态密码器服务,影响范围为调用到动态密码器服务的业务功能。
2.2.2.数据库的影响范围
该服务对数据库的影响范围主要有动态密码器存储表,用户表,第三方服务表共三张。其中使用动态密码器存储表存储动态密码器的信息。另外,使用动态密码器服务还需要查询用户表以及第三方服务表。
2.3.知识储备
2.3.1.什么是微服务

微服务就是将单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中,服务间采用轻量级通信机制(通常为HTTP方式)。各个服务可以使用不同的语言开发,使用不同的数据存储技术。
2.3.2.微服务体系需要用到的主要技术
<1>SpringBoot
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。它默认配置了很多框架的使用方式,就像maven整合了所有的jar包一样。它具有少配置,开箱即用,轻量级等优点。是微服务体系构建中必不可少的技术之一。
<2>SpringCloud
作为现在微服务体系的主流技术,SpringCloud同样具备开箱即用的特性。它无缝集成SpringBoot,且组件齐全,同时还拥有十分丰富的文档和活跃的社区。另外,它也被喻为全家桶,拥有非常丰富的组件如Eureka,Ribbon,Feign,Hystrix,Zuul等。在这里不详细展开,有兴趣的读者可以阅读我的Spring系列专栏,在那里会有详细的讲解。
2.3.3.其他技术
除了上面所提到的Spring系列技术,读者还需要掌握微服务体系的构建思路,只有明确整个架构思路,才能更好的对单体应用进行改造。
传统SSM项目改造SpringBoot微服务实践_第2张图片
这里简单描述下,原有的单体应用中的模块被拆分到基础服务和用户服务中,当单体应用需要请求用户服务时,会通过Zuul网关,将请求发送给用户服务;而在微服务之间,采用Feign来进行微服务的调用;各个微服务需要将自己注册到Eureka注册中心上,实现服务的暴露以供服务消费者调用。感兴趣的读者可以阅读相关书籍。
三.开始改造
3.1.改造思路

下面开始做项目改造,在本次改造计划中,主要目标是将动态密码器服务迁移到微服务中,并在单体应用中的该服务调用转移到对微服务的调用。具体思路如下:
3.1.1.改造微服务
<1>将动态密码器服务的相关代码迁移到微服务中,首先明确动态密码器服务的主要功能是通过产生动态密码来保证一些交易的安全操作,因此将其归属于基础服务,因此将该服务迁移到基础服务中,下文用base服务来指代基础服务。
<2>在明确了服务所属的具体位置后,还需要明确服务的依赖关系。动态密码器服务在使用过程中,是一个用户对应绑定一个动态密码器,因此需要依赖用户服务(下文用user服务来指代),同时,需要调用一些第三方服务,因此需要依赖第三方服务(下文用thirdparty服务来指代)。依赖后的微服务依赖关系如下:
传统SSM项目改造SpringBoot微服务实践_第3张图片
也就说,在改造动态密码器服务的过程中,还需要将需要依赖的服务也一并迁移,将动态密码器服务放入base服务中,依赖的用户服务放到user服务中,而依赖的第三方服务则放到thirdparty服务中。
<3>数据源的改造
按照经典理论,不同的微服务应该拥有自己的数据源,但是在本次改造过程中,并没有对数据源进行改造,而是直接连接之前的库,原因主要有2个:第一是如果将对应服务的表也迁移出来,那么之前单体应用所做的join等操作将会失效,需要考虑;第二是拆出后,数据库数量会增多,增加运维成本,这个在前期需要尽量避免。
3.1.2.改造单体应用
改造完微服务后,就需要改造单体应用了,将之前单体应用中调用到动态密码器服务的逻辑改成调用微服务的逻辑,采用HTTP+POST的方式进行调用,请求将通过Zuul网关发送到base服务中,而base服务将通过Feign调用user服务和thirdparty服务。
3.1.3.后续改进
<1>增加Hystrix熔断器,做微服务的熔断。
<2>增加日志配置,对关键位置进行日志输出,以便后续排查问题。
3.1.4.废弃旧逻辑
上述工作完成后,最后废除原来的动态密码器的旧逻辑,至此,传统项目中的动态密码器服务被彻底改造到微服务体系中。
3.2.改造过程中遇到的问题及解决
下面就改造过程中遇到的问题进行记录并提出相应的解决方案:
<1>迁移过程中需要迁移较多的类,这些类的位置如何确定?
A:具体的逻辑类放在微服务包中,而需要被引入的类(vo类)放在API包中。
<2>引入的类如何使用?
A:引入的类需要被Spring容器管理,原有的单体应用通过xml的方式配置Bean,而在微服务中可以通过JavaConfig或者注解的方式来配置Bean。
<3>单体应用,微服务之间的调用手段?
A:单体应用调用微服务可以通过HTTP的方式进行远程调用;而微服务调用微服务则通过Feign组件来调用。Feign组件可以做成API包的方式,需要调用时引入即可。
<4>某些微服务的Service层需要直接被调用如何处理?
A:对微服务的Service层单独设置Controller层并且配置Feign Client即可。
<5>微服务都需要的公共配置(类)如何保存?
A:主要有两种方式。第一种方式是将公共配置类抽离,放到公共包中,需要时直接引入;第二种方式是在各个微服务之间做冗余,不过这种方式管理上会有不便。因此,笔者采用第一种方式。
四.改造后
笔者在改造完成中,并没有直接废除旧逻辑,而是采用二者并存的方式。通过开关来控制动态密码器服务的调用逻辑,如果打开开关,将会调用微服务的动态密码器服务,如果关闭开关则会直接使用原有单体应用自身的动态密码器功能,这主要是为了保证万无一失。在出现问题时可以及时处理,减低微服务事故发生对项目的影响。后续上线后稳定一段时间,再移除开关,并废除旧逻辑。
五.总结
单体应用向微服务的转变是一项巨大的工程,里面涉及很多理论基础,需要深入学习才能较好的完成。同时,理论知识的学习,还需要深入的实践才能熟练掌握。希望通过本文,让读者对整个改造过程有所了解,并能准确地运用在生产实践中。

你可能感兴趣的:(生产实践,分布式)