关于从单体架构升级到微服务架构的实践经验和踩坑指南

1.1 企业面临的微服务升级困境

在微服务盛行之前,很多企业应用都是基于单体架构的研发。

但随着技术的不断发展,如今很多企业可能都面临着如何将自己的单体企业应用进行微服务升级改造的问题。

今天这篇博文博主来跟大家分享一些单体架构升级到微服务的一些经验。

1.2 怎么拆?

要想成功的将一个单体应用完美的拆分成微服务是一个巨大的工程,如何拆分过细,会造成系统的维护成本过高,从而导致失败。

1.2.1 根据业务之间的联系是强关联还是弱关联?

比如电商模块和活动模块,彼此之间是一个相对独立的业务,就可以初步进行粗略拆分。

然后电商模块和活动模块之间的调用从原来的本地方法调用到进程与进程之间的调用

远程调用方式有三种:

1.我们可以通过Spring Cloud Open Feign 聚合API 实现,如果是初创公司,人员不是很充足建议使用这种。

  • 值得注意的是,Spring Cloud Open Feign 是可以单独使用的,并非必须使用 Eureka 或Zookeeper 注册中心那种繁琐方式。
  • 相对而言,如果使用最简化方式,那么使用Nginx作为网关和负载均衡是比较合适的。
  • 另外,不建议使用OkHttpClient或者RestTemplate 来实现微服务与微服务之间的远程调用,因为如果你这么做,会需要额外处理很多不必要的东西,比如数据的序列化和反序列化,异常的处理等等。

2.也可以通过使用基于rpc协议的gRpc或者Spring Cloud Alibaba,适合有一个比较完整的团队来做。

3.也可以通过消息中间件,对于一些实时性不是很强的,可以延迟处理的,可以考虑使用这种方式,实时性强的建议前两种。

1.2.2 根据业务需要即时响应还是可以有延迟?

如果有些接口调用需要最快的速度返回,需要低延迟,那么这种业务模块不适合拆分。

1.2.3 面向接口,一部分一部分的拆,而不是一下子把项目全部重写。

有些企业直接把所有项目全部重写,改造微服务,这种成本说实话超级大,实际上很不现实,这么玩一定会玩死的。

因为来自BRD(业务需求)和PRD (产品功能需求)需求一直在不断进行更新迭代, 同时对两套系统进行开发迭代,成本太高。

所以一种好的方式是将项目的代码使用设计模式进行梳理,比如面向接口编程,一个接口多个实现类,一个是基于本地实现,一个基于远程调用,这样做的一个好处就是可以慢慢的换血,对系统的影响最小,一旦远程调用方式发生紧急问题,只需要切换本地实现类即可,当远程调用实现类的实现方式成功稳定运行后,就可以慢慢去掉本地方法的实现。

1.2.4 使用持续集成

我们知道一旦将企业的单体应用拆分成多个应用之后,如果还手动部署的话,那么耗时耗力,效率低下。

因此最好尝试使用Jenkins 或其他方式实现自动化构建部署,这样我们才有最大的精力专注于业务。

当然持续集成也大体有三种方式,

  • 一种是持续集成构建jar包的方式,

如果是初创公司,人员配备比较少,那么建议最好首选使用第一种持续构建jar的方式。

因为这种方式迁移成本最低。

  • 另外一种是容器化成docker 镜像。

如果人员规模比较大,专人专职,分工明确,可以考虑使用,当然如果使用这种方式,最佳实践是引入K8S进行容器编排。

只是这种相对来说,对于很多企业来说,成本比较大,需要有专人对K8S和容器编排方面有比较深的了解。

  • 还有一种是基于云托管

这种相对于部署和编排全部交给云处理,精力可以放到业务上,公司不差钱可以考虑这种方式。

1.2.5 日志处理

由于传统的单体应用拆分成微服务后,日志将会变得混乱起来,每个微服务假如都有dev,test,uat,prod 环境,那么系统调用一旦出现异常,想要排查,如果涉及的微服务不多还好,如果微服务很多,那么就简直是个灾难。

解决这种方式的一种比较好的解决方案是集成ELK/EFK.

关于ELK的大名,相信大家耳熟能详,肯定知道E就是Eleastisearch,L 就是Logstash,K 就是Kibana.

其中,Logstash 用于采集收集日志,ES 用于对数据进行处理,建立倒排索引, 构建查询API. K则作为可视化界面管理。

但是实际上,如果真实开发过,你一定会了解到只使用ELK 是远远不够的。

为什么?

因为Logstash 这个日志收集框架虽然功能强大,但是也很耗费服务器资源,所以一种好的优化方式是采用Filebeat 来采集日志。

因为FileBeat 是一个轻量级的日志采集框架,耗费服务器资源最小,可用于快速采集日志使用。

之后再通过Logstash 进行日志初步处理,处理完成后交给ES, 最后ES 生成索引后,交给Kibana 进行处理。

当然根据实际业务的不同可能有不同的组合,也可能会中间会引入Apache Kafka,Apache Pulsar 等。

1.2.6 生成文档

一旦将单体应用拆分多个微服务之后,各个微服务之间的所有API 应该都集成Swagger ,自动生成调用文档。

这是因为,虽然我们有了ELK/EFK 的日志收集工作,但是对于微服务的测试仍旧一个难题。

比如测试一个业务流程,可能涉及到多个微服务,写代码去挨着测试简直是一个灾难。

所以,最好集成Swagger ,比如一个业务流程,微服务A需要调用微服务B,微服务B需要调用微服务C,微服务C调用微服务D.

A->B,C->D 都没问题,B-> C节点有问题,那么如果想测试B->C节点,那么你如果手动测试,可能需要构造很多参数,非常麻烦。

1.2.7 安全模块使用Spring Security + 过滤器

我们知道,如果使用了Swagger, 不对微服务做权限检验是很危险的。

如果swagger 和 App 或后台的API 都适用过滤器,自定义权限验证,是相对比较麻烦的。

因此,从开发最简单化方式来说,一种比较简便的方式是Spring Security 基于Session的权限校验作为Swagger 文档的权限拦截,而对于App或后台管理系统采用自定义过滤器的方式来做一个统一鉴权中心。

每个微服务之间调用不需要自己重写一遍鉴权逻辑,而是通过远程调用方式实现。

当然,如果企业人员充足,技术开发时间充足,也可以将swagger 文档鉴权也弄到自定义权限验证系统里面也行。

1.2.8 集成邮件通知

每个微服务重启部署成功或发生重大故障之后应该能自动发送一封邮件通知,确保通知到负责该模块的微服务研发团队。

每个微服务应该都支持图形用户界面配置邮件通知者,这对于团队管理和研发故障预警有非常大的帮助。

1.2.9 应该使用分布式缓存或数据库静态值来控制开关

在单体架构的时候假如我们在应用程序中设置了一个静态变量,用来控制某个功能打开还是关闭。

但是如果到微服务架构的时候,我们就不能再这样做了,而应该使用分布式缓存,或数据库静态值来充当开关。

为什么?

因为微服务架构下基本上会有负载均衡,当微服务A1和微服务A2 做了负载均衡,假设微服务A1和微服务A2在应用内都有一个静态变量,变量含义为默认某个功能开关为false,当我们调用API 改变微服务A1 的功能开关修改为true, 但是可能只有微服务A1 的静态变量变成了true, 微服务A2 的静态变量还是原来的false.

解决思路就是使用分布式共享缓存Redis 或 数据库中定义静态常量来存放这个开关。

另外,我们知道所谓微服务的本质是进程间的通信,API 的调用是通过Spring Cloud Open Feign 实现接口聚合。

但是这种聚合出来的数据因为有些数据是RPC调用,可能会有延迟,所以如果接口数据返回不是千人千面那种,可以使用Redis 缓存接口数据,然后定时更新即可,这样可以优化接口响应速度。


本篇完~

如果喜欢我的文章可以点赞,关注或评论,想和我一起交流技术,看我更多学习心得可免费扫码加入我的知识星球。
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

极客星云

谢谢认可,希望对你的学习有帮助

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值