公司在推进降本增效,在尝多种手段之后,发现应用太多,每个应用都做跨机房容灾部署,则最少需要 4 台机器(称为容器更合适)。那么,将相近应用做一个合并,减少维护项目,提高机器利用率就是一个可选方案。

经过前后三次不同的折腾,最后探索出来一个可行方案。记录一下,分享出来,希望对有相关需求的研发童鞋有所帮助。下面按照四种可能的方案,分别做介绍。另外,为了方便做演示,专门整了两个演示项目:

diguage/merge-demo-boot — 合并项目,下面简称为 boot。
diguage/merge-demo-web — 被合并项目,下面简称为 web。

一、Jar 包引用

这个方式,可能是给人印象最容易的方式。仔细思考一下,从维护性的角度来看,这个方式反而是最麻烦的方式,理由如下:

1.web 项目每次更新,都需要重新打包发布新版; boot 项目也需要跟着更新发布。拉一次屎,脱两次裤子。属实麻烦。
2.还需要考虑 web 项目的加载问题,类似下面要描述的,是否共用容器:共用容器 — 这是最容器想到的方式。但是这种方式,需要解决 Bean 冲突的问题。不共用容器 — 这种方式需要处理 web 容器如何加载的问题。默认应该是无法识别。
3.

基于这些考虑,这种方式直接被抛弃了。

二、仓库合并,公用一套容器

这是第一次尝试使用的方案。也是遇到问题最多的方案。

1.将两个仓库做合并。
1.将 web 仓库的地址配置到 boot 项目里: git remote add web git@github.com:diguage/merge-demo-web.git;
2.在 boot 项目里,切出来一个分支: git switch -c web;
3.将 web 分支的提交清空: git update-ref -d HEAD,然后做一次提交;
4.将 web 项目的代码克隆到 web 分支上: git pull --rebase --allow-unrelated-histories web master;注意,这里需要加 --allow-unrelated-histories 参数,以允许不相干的仓库进行合并。
5.从 boot 项目的 master 分支上,切出来一个合并分支: git switch -c merge;
6.将 web 项目向 boot 项目合并: git merge --allow-unrelated-histories web;注意,这里需要加 --allow-unrelated-histories 参数,以允许不相干的仓库进行合并。
7.处理代码冲突,完成合并即可。
2.配置文件的合并于归整。为了防止同名配置文件冲突,需要把 web 项目的配置文件调整到一个文件夹下,这里设定为 web 目录。然后,需要把 web 项目的配置文件,让 boot 可以加载到。这个调整相对简单,只需要一个注解即可 @ImportResource({"classpath:web/spring-cfg.xml"})。
3.调整完配置文件,接着遇到的问题就是上面提到的 Bean 冲突的问题。由于两个项目都访问相同的数据库, Dao 及 Service 层很多很多类都是同名的。另外,在 web 项目里,Dao 是基于 iBATIS 开发的,而在 boot 项目里,DAO 是基于 MyBATIS 开发的。所以,只能给 web 项目的相关代码做重命名(严谨一点是给 Spring Bean 的 beanName 做重命名操作)。这又带来了新问题:原来的项目里,注入方式是根据名称注入的,就需要改动大量的代码,给相关的 Bean 变量做重命名操作。这无形中增加了很多的复杂度和不确定性。

经过不断折腾,这种方式被迫放弃。

三、仓库合并,Spring Boot 父子容器

在经过上述方式折腾后,就想到了另外一个方案:可以考虑使用父子容器的方式来搞。接着就查到了这篇文章: Context Hierarchy with the Spring Boot Fluent Builder API。感觉这种方式挺不错,就尝试了一下。

1.代码合并及文件调整,跟上述步骤类似,这个后面就不再赘述。
2.按照文章中的介绍,使用父子容器的方式来加载两个项目。代码如下:
3.原以为,这种方式属于父子两个容器,即使有同名的 Bean 应该也没有影响。但是,经过实践才发现,上面这个猜测是错误的。Spring Boot 在启动的时候,它背后做了检查,如果两个容器有同名的 Bean,它也会报错。也会带来像上述方式那样的大量重命名。折腾一两天,最后还是放弃了这种寄予厚望的方式。
package com.diguage.demo.boot;

import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource; /**
* @author D瓜哥 · https://www.diguage.com
*/
public class DemoBootApplication { public static void main(String[] args) {
new SpringApplicationBuilder()
.parent(BootConfig.class).web(WebApplicationType.NONE)
.child(WebConfig.class)
// 如果有第三个项目,可以作为子容器的兄弟容器加载。
// .sibling(SiblingConfig.class)
.run(args);
} @Configuration
@ImportResource({"classpath:spring-cfg.xml"})
@ComponentScan(basePackages
  Spring Boot 背后是否做了检查,这个是根据报错信息的猜测,没有翻看代码,所以这个猜测有一定的不确定性。有机会翻一下代码,查看一下具体原因。

革命尚未成功,且听下回分解……

作者:京东科技 李君

来源:京东云开发者社区 转载请注明来源

Spring 应用合并之路(一):摸石头过河 | 京东云技术团队的更多相关文章

  1. 《跟唐老师学习云网络》 -第4篇 router路咋走啊【华为云技术分享】

    [摘要] 好了,到这里至少你应该能看懂路由表信息了.给你一个目的IP,你也应该知道它会使用哪一条路由了. 路怎么走就看骚年你了~ 一.路由 其实关于网络大家遇到最多的问题就是:卧 槽,为什么不通啊! ...

  2. Spring Boot 最流行的 16 条实践解读!【华为云技术分享】

    置顶:华为云618大促火热进行中,全场1折起,免费抽主机,消费满额送P30 Pro,点此抢购. Spring Boot是最流行的用于开发微服务的Java框架.在本文中,将与大家分享自2016年以来笔者 ...

  3. Struts2+Spring集成合并

    前边单独总结了Struts2,Spring和Ibaits框架了,那么怎么结合使用呢?这次先来看一下Sturts2和Spring的集成合并.其实挺简单的,就是导入各自的jar包以及连接彼此的jar包,分 ...

  4. ArcMap合并之路 -- 该段路合并成一个完整的路

    #1: 用 Arctoolbox\Data Management Tools\Generalization\dissolve 工具 #2: Options:dissolve field 项选" ...

  5. Spring Boot 学习之路二 配置文件 application.yml

    一.创建配置文件 如图所示,我们在resources文件夹中新建配置文件application.yml   结构图 二.一些基本配置 server: port: 8090 //配置端口 session ...

  6. .net core+Spring Cloud学习之路 二

    前言: 原本计划这次写一下搭建eureka群集.但是发现上次写的只是服务的注册,忘了写服务的发现,所以这次先把服务发现补上去. 我们基于上篇文章,再新建两个.net core web api项目,分别 ...

  7. .net core+Spring Cloud学习之路 一

    文章开头唠叨两句. 2019年了,而自己参加工作也两年有余了,用一个词来概括这两年多的生活,就是:“碌碌无为”. 也不能说一点收获都没有,但是很少.2019来了,我立志要打破现状,改变自己,突破自我. ...

  8. Spring的自学之路之入门

    认识Spring Spring是分层的Java SE/EE 应用一站式的轻量级开源框架,以Ioc(Inverse of Control,控制反转)和AOP(Aspect Oriented Progra ...

  9. Spring学习开发之路——使用JavaBean代替EJB

    Spring框架是由于软件开发的复杂性而创建的.Spring使用的是基本的JavaBean来完成以前只可能由EJB完成的事情.然而,Spring的用途不仅仅限于服务器端的开发.从简单性.可测试性和松耦 ...

  10. Spring框架自学之路——简易入门

    目录 目录 介绍 Spring中的IoC操作 IoC入门案例 Spring的bean管理配置文件 Bean实例化的方式 Bean标签的常用属性 属性注入 使用有参构造函数注入属性 使用set方法注入属 ...

随机推荐

  1. DTSE Tech Talk | 第11期:深入浅出畅谈华为云低时延直播技术

    摘要:详解华为云低时延直播在时延.首屏.卡顿率等体验的优化方案,及如何快速接入方法. 本文分享自华为云社区<DTSE Tech Talk | 第11期:深入浅出畅谈华为云低时延直播技术>, ...

  2. 如何做好分支管理,保证高效CI/CD?

    摘要:一文讲述git分支管理策略. 本文分享自华为云社区<如何做好分支管理,保证高效CICD?>,作者:华为云PaaS服务小智. 引言 CI/CD是DevOps 的基础核心,做好CI/CD ...

  3. 一分钟带你了解Huawei LiteOS组件开发指南

    摘要:本文将基于Huawei LiteOS系统,从组件定义开始带你走进组件开发指南. 本文分享自华为云社区<一分钟带你了解Huawei LiteOS之组件开发指南>,作者: Lionlac ...

  4. 带你学会区分Scheduled Thread Pool Executor 与Timer

    摘要:本文简单介绍下Scheduled Thread Pool Executor类与Timer类的区别,Scheduled Thread Pool Executor类相比于Timer类来说,究竟有哪些 ...

  5. 华为云开源的Karmada正式成为CNCF首个多云容器编排项目

    摘要:CNCF(云原生计算基金会)正式接纳由华为云贡献的多云容器编排项目Karmada,迎来CNCF首个多云容器编排项目. 北京时间9月15日,CNCF(云原生计算基金会)正式接纳由华为云贡献的多云容 ...

  6. CompletableFuture 打桌球的应用

    CompletableFuture 使用 @Test public void billiardTest() throws Exception { // 创建点外卖线程: CompletableFutu ...

  7. 【scikit-learn基础】--『监督学习』之 谱聚类

    谱聚类算法基于图论,它的起源可以追溯到早期的图分割文献.不过,直至近年来,受益于计算机计算能力的提升,谱聚类算法才得到了广泛的研究和关注. 谱聚类被广泛应用于图像分割.社交网络分析.推荐系统.文本聚类 ...

  8. BZOJ 2038: [2009国家集训队]小Z的袜子【莫队算法裸题】

    作为一个生活散漫的人,小Z每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿. 终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命. 具体来说,小Z把这N只袜子从1到N编号,然后从 ...

  9. var _ I = (*T)(nil)

    学习的时候看到这样一行代码 var _ Codec = (*GobCodec)(nil) 查了一下后,得到该语句的作用为:检查GobCodec这个结构体是否实现了Codec这个接口 空白标识符_代表变 ...

  10. kafka搭建二、集群搭建

    系列导航 一.kafka搭建-单机版 二.kafka搭建-集群搭建 三.kafka集群增加密码验证 四.kafka集群权限增加ACL 五.kafka集群__consumer_offsets副本数修改 ...