SpringBoot单体项目拆微服务好麻烦?试试模块化单体:从循环依赖解释单体到微服务的架构演进
单体架构、模块化单体、微服务架构的区别和运用策略情况分析-循环依赖开发项目的时候经常会遇到代码量庞大、业务高度耦合的情况有时候甚至可能出现循环依赖的情况Description: The dependencies of some of the beans in the application context form a cycle: courierTaskController ┌─────┐ | courierTaskServiceImpl ↑ ↓ | orderServiceImpl └─────┘CourierTaskService类注入OrderService类的对象而OrderService又注入CourierTaskService的对象JVM便会这样报错。虽然可以在一个注入上加上Lazy来缓解但这只是掩耳盗铃不能改变业务过于耦合的问题下完订单需要给快递员分配任务给快递员分配任务需要更新订单状态需要一个用户端web服务先调用订单模块保存订单再调用快递员模块分配任务同时需要快递员端web服务取件调用快递员模块更新任务状态完成之后调用订单模块更新订单状态。这样各司其职就降低了耦合度这时候就可以考虑模块化单体、以及后续考虑拆分微服务了但是在你急着拆分微服务之前。需要明白单体架构、模块化单体微服务架构的区别。1单体架构大泥球单体Monolith如同一个小作坊所有员工在一个房间里需要调用其他服务直接喊一嗓子(Autowired)就行。src/main/java/com/shop ├── controller/ │ ├── UserController.java │ └── OrderController.java ├── service/ │ ├── UserService.java │ └── OrderService.java // 里面直接 Autowired UserService ├── entity/ │ ├── User.java │ └── Order.java └── dao/ ├── UserDao.java └── OrderDao.java这样所有的服务都在一个JVM中因此可以Autowired引入各种各样的服务。多么方便是吧但是代价是如此方便的注入对象让人难以思考低耦合度的架构这样可以实现诶就这样实现了。当后续项目越来越庞大你发现改一个UserService服务方法就需要动什么订单优惠券积分等大量服务单体弊端就展示出来了。2模块化单体Modular Monolith从单体架构直接到微服务架构就像一个小孩刚学会了说话就让他背古诗一样。引入微服务不仅要引入nacos、feign、gateway等等依赖还要各种复杂的配置。不是很熟练的开发者可能要花上好几天时间才能拆分完成。如果你只是嫌代码结构太乱业务太耦合那就不用急着搞微服务先拆成一个个文件夹这就是所谓模块这样就实现了业务分离耦合度降低。除此之外模块化单体不需要微服务那样跑多个服务服务仍然在一个JVM中只是看起来像是被分成了多个微服务。这样性能开销也不会太大。这就是模块化单体的意义。模块化单体就是给单体披上了一层微服务的外衣。如下图的结构以下只讲这一种形式shop-parent (父工程 统一管理依赖版本) │ ├── shop-common/ // 1. 公共工具类、全局异常、公共DTO │ ├── shop-user/ // 2. 用户业务模块 │ ├── user-api/ // api-对外暴露的接口、DTO、枚举 │ ├── user-domain/ // domain-实体、Repository接口 │ └── user-service/ // service-具体的服务 │ └── shop-order/ // 3. 订单业务模块 ├── order-api/ ├── order-domain/ └── order-service/把每个模块分成一个个文件夹里面在分为apidomianservice三个模块。先是在业务上分级然后在技术上分级。api模块就提供了这个服务如user服务的api接口其他服务引入api依赖就可以使用api里面的方法就是这个user服务向外暴露的方法如getUserByUserId这样。模块化单体让单体成为加以约束的单体。虽然物理层面上还是用着单体的方法运行但是架构却是微服务的。 3微服务(Microservices)到这个层面一般都是项目过大人过多局部性能低需扩容系统的情况了。微服务的好处有可以各模块独立打包发布这样不同业务团队可以根据自己的进度各自发布互不阻塞对于高流量的模块可以独立扩容不用整体扩容浪费系统资源。️一个模块出问题其他模块可以继续工作而不是全部宕机修复时也不用为了一个服务把整个服务都停掉把上述模块化单体的模块变成微服务就是在物理上也给服务们隔离了模块化单体使用AutoWired等注解仍然可以成功注入对象因为服务仍在一个JVM中。但是微服务架构下的服务必须用feign或nacos的技术栈来向其他服务发请求。这时候数据库就可以用多个了你在每个服务的yml中都可以各自配置服务独立性大大加强当然代价就是运维成本极高。️4运用策略业界推崇单体优先而不是上来就搞复杂的微服务微服务不是为了预防而是真真正正的解决实际的痛点才考虑使用。如果你开发一个项目一开始可以先从单体架构入手后续遇到代码耦合的问题考虑模块化单体后续真的有微服务的需求再拆微服务。5尾声关于内容问题的指出可以发在评论区可以给个赞吗这会让博主高兴一整天