Java WEB系统微服务化迁移

支撑互联网公司运行的庞大后端服务系统经历了原始的BS架构设计、前后端分离、模块化组件、系统分层设计的进化,从计算资源的虚拟化到今天容器技术的应用,互联网一直在朝着资源高效配置、分布式集群服务的方向进发。

Docker作为当下最流行的容器化技术,相比于运行在实体物理机上的虚拟机技术,它具有轻量级资源隔离、快速部署、持续交付、版本控制、 可移植、开放技术等特点。

如果采用虚拟机技术去部署一套系统,需要几个步骤:

  1. 分配物理资源(CPU\内存\网络)
  2. 开机启动运行
  3. 安装系统运行时支撑环境(模版)
  4. 发布生产系统
  5. 上线。

采用Docker需要如下几个步骤:

  1. 拉取Docker Image
  2. 发布生产系统
  3. 上线

相比来看可能就会发现,Docker相当于把最繁琐最耗时的工作帮助我们解决了。Docker运行在(特定)操作系统之上,只需要一条命令即刻启动;通过Docker Image将运行时配置、依赖管理、版本管理集成一个Dockerfile描述文件中标准化,快速解决原始虚拟机技术中的1、2、3步骤。如果再搭配Google出品的Kubernetes容器管理工具更加得心应手。

与Docker并行出现一个架构模式-微服务,它并不是一种全新的架构体系,更确切的说是一种架构的思考。在经历了模块化、组件化、服务化之后,系统的架构设计实现复杂、服务调用关联度高等问题困扰着一个系统的稳定性和开发难度。微服务是在原有的服务治理的基础上,将原有系统服务的粒度进行再切分使得服务之间的耦合性降至最低,同时不依赖于过多的外部运行时环境,对外暴露的输入输出可能只是一个JSON、XML数据集,可以实现大规模的快速部署运行。这些特点与Docker的容器化优势不谋而合,这也是当前微服务实践采用比较多的一种方式。

Spring Boot在微服务概念出现之前已经发布了有一段时间,但并没有大行其道,大家对于Java Web的项目更倾向于原有Servlet Container Server的部署模式。随着微服务的出现,Spring Boot再次引起了大家的注意,同时Spring在被收购后也在朝着云服务商的方向上进发,推出了自己的云服务平台。

相比一切全新的服务系统,遗留的Java WEB系统如何进行更好的迁移使用微服务,是需要考虑的一大问题。当前的项目中框架采用了Freemarker+Spring+Hibernate的方式,Spring的配置是原有的XML配置方式,与Spring-Boot推荐的注解配置相比,迁移难度较大。

Spring-Boot使用注解配置剥离了XML的配置方式,使用内嵌式Servlet Container(Jetty\Tomcat\Undertow)来实现服务的HTTP通信、监控、交互。与此相对照,能否维持XML配置不变,仅使用内嵌Servlet Container来提供服务呢?答案是:可以。

采用Tomcat Embed作为默认的Servlet Container,通过Tomcat Bootstrap中Host、Port配置来实现HTTP服务,指定WEB路径的方式来提供Spring XML配置部分和其他WEB资源,这样就基本实现了原有Java WEB系统的服务化迁移。

在迁移测试过程中,也遇到了几个坑。

1、Gradle编译工具对JAR包的支持度不够完善,需要额外的插件来实现Eclipse FatJar的功能。

apply plugin: "com.github.johnrengelman.shadow"

2、如果自定义Jar合并时,一定要注意Spring Schema文件的合并。在不使用插件的情况下,会导致spring schema XSD文件的丢失。需要在插件支持下通过tramformer来合并。

mergeServiceFiles('META-INF/spring.*')

如果单独使用Maven来打包之需要通过修改POM文件来实现。

相关资料

Docker Spring-Boot Gradle FatJar Plugin Tomcat Embed