微服务是这几年非常火的架构风格很多公司都在从单体应用向微服务架构演进但是微服务不是银弹不是所有项目都适合微服务也不是拆成微服务就一定好微服务有它的优势也有它的挑战和复杂度。
我做过几个项目从单体到微服务的演进也踩了很多坑总结了很多经验今天就来分享一下微服务架构设计的一些思考和经验。
一、单体应用的问题
在讲微服务之前先说说单体应用的问题因为微服务就是为了解决单体应用的问题而产生的。
单体应用就是把所有的功能都放在一个应用里比如一个电商网站用户商品订单支付等等都在一个应用里打包部署这就是单体应用。
单体应用的优点是简单开发简单部署简单调试简单适合小项目和项目初期但是随着项目越来越大功能越来越多团队越来越大单体应用的问题就会越来越明显。
1. 代码庞大难以维护
单体应用所有的代码都在一个项目里随着功能增加代码会越来越庞大几十万行甚至上百万行代码找一个功能都很麻烦修改一个地方可能会影响其他地方很容易出bug维护成本很高。
2. 编译部署慢
代码庞大编译就慢每次修改一点代码都要重新编译整个项目等很久部署也慢整个应用一起部署启动也慢影响开发效率和发布效率。
3. 技术栈固定难以升级
单体应用技术栈是固定的一旦选定了技术栈就很难改变比如用了PHP就很难换成Java或者Python即使某个功能用其他语言更合适也很难换而且框架版本升级也很麻烦因为整个项目一起升级风险很大。
4. 扩展不灵活
单体应用扩展的时候只能整个应用一起扩展比如订单功能压力大需要扩展但是只能把整个应用都扩展部署多台机器其他功能比如用户商品也跟着扩展浪费资源不能按需扩展。
5. 团队协作困难
团队大了之后多个团队一起开发一个单体应用代码冲突多合并代码麻烦发布也需要协调所有团队一起发布很麻烦影响开发效率而且一个团队的代码出了问题可能会影响整个应用影响其他团队。
6. 可靠性差
单体应用所有的功能都在一个进程里一个功能出了问题比如内存泄漏死循环可能会导致整个应用崩溃所有的功能都不可用影响范围大可靠性差。
因为这些问题所以微服务架构就应运而生了。
二、什么是微服务
微服务就是把一个大的单体应用拆成多个小的服务每个服务独立开发独立部署独立运行服务之间通过API通信比如HTTP REST或者消息队列等等每个服务负责一个单一的功能比如用户服务商品服务订单服务支付服务等等这就是微服务。
微服务的核心思想就是"单一职责"和"高内聚低耦合"每个服务只负责一个功能内聚性高服务之间通过标准的API通信耦合性低可以独立开发部署扩展升级。
微服务和SOA(面向服务的架构)有点像但是也有区别SOA更偏向企业级集成用ESB(企业服务总线)通信比较重微服务更轻量用HTTP REST或者消息队列通信更灵活更适合互联网项目。
三、微服务的优势
微服务之所以这么火是因为它有很多优势能解决单体应用的很多问题。
1. 服务小易于维护
每个微服务只负责一个功能代码量小逻辑简单容易理解和维护修改一个服务不会影响其他服务出bug的概率低维护成本低。
2. 独立部署发布快
每个服务独立部署修改了一个服务只需要重新部署这个服务就行不用部署整个应用部署快风险小发布频率可以更高能快速迭代快速上线。
3. 技术栈灵活
每个服务可以选择最适合的技术栈比如用户服务用PHP订单服务用Java推荐服务用Python等等不用所有服务都用同一个技术栈而且升级技术栈也只需要升级一个服务风险小。
4. 按需扩展
每个服务可以独立扩展哪个服务压力大就扩展哪个服务不用扩展整个应用节省资源比如订单服务压力大就多部署几台订单服务其他服务不用扩展很灵活。
5. 团队独立协作好
每个团队负责一个或者几个服务独立开发独立部署不用和其他团队太多协调代码冲突少发布也不用一起发布团队自治效率高。
6. 可靠性高
一个服务出了问题不会影响其他服务其他服务还能正常运行影响范围小可靠性高而且可以快速定位问题出在哪个服务方便排查和修复。
四、微服务的挑战
微服务有很多优势但是也不是银弹也有很多挑战和复杂度不是所有项目都适合微服务在决定用微服务之前一定要了解这些挑战。
1. 分布式系统复杂度高
微服务是分布式系统分布式系统比单体应用复杂很多要处理网络延迟网络分区服务调用失败超时重试幂等分布式事务数据一致性等等问题这些都很复杂需要有经验的团队才能处理好。
2. 服务拆分难
把一个大的单体应用拆成多个微服务不是一件容易的事拆得太细服务太多管理复杂拆得太粗和单体没什么区别而且服务边界怎么划服务之间怎么通信数据怎么分这些都需要仔细考虑拆不好反而会更麻烦。
3. 运维复杂
微服务服务多部署的实例也多运维很复杂需要自动化部署自动化扩缩容监控告警日志收集链路追踪等等都需要配套的工具和平台运维成本高需要有专业的运维团队或者DevOps能力。
4. 调试排错难
单体应用调试简单在一个进程里打断点就行微服务一个请求可能经过多个服务出了问题不知道是哪个服务的问题需要链路追踪分布式日志等等才能定位问题调试排错很麻烦。
5. 数据一致性难
单体应用数据都在一个数据库里用数据库事务就能保证一致性微服务每个服务有自己的数据库跨服务的操作需要分布式事务但是分布式事务性能差实现复杂一般用最终一致性来代替但是最终一致性开发复杂也有数据不一致的风险。
6. 服务通信开销
微服务服务之间通过网络通信比单体应用的进程内调用慢很多而且有网络开销和延迟如果服务拆分不合理调用链太长会导致性能差响应慢。
所以微服务不是银弹有优势也有挑战小项目团队小功能简单就不要用微服务单体应用更合适只有项目大了团队大了单体应用的问题很明显了才考虑微服务。
五、微服务的技术栈和组件
微服务需要很多配套的技术和组件才能很好地运行下面介绍一些常用的组件。
1. 服务注册与发现
微服务服务多实例也多需要服务注册与发现组件来管理服务的地址和状态服务启动的时候注册自己的地址调用其他服务的时候从注册中心查询服务地址常用的注册中心有EurekaConsulNacosZookeeper等等。
2. API网关
API网关是微服务的入口所有的请求都先经过API网关然后转发到对应的服务API网关负责路由负载均衡鉴权限流熔断日志监控等等常用的API网关有KongZuulSpring Cloud GatewayNginx等等。
3. 配置中心
微服务服务多配置也多需要配置中心来统一管理所有服务的配置修改配置不用重新部署服务能动态刷新常用的配置中心有Spring Cloud ConfigApolloNacos等等。
4. 熔断降级限流
微服务调用链长一个服务出问题可能会导致整个调用链都出问题甚至雪崩所以需要熔断降级限流组件来保护系统常用的有HystrixResilience4jSentinel等等。
5. 分布式事务
微服务跨服务的操作需要分布式事务常用的方案有2PCTCCSaga本地消息表事务消息等等常用的框架有Seata等等。
6. 链路追踪
微服务一个请求经过多个服务需要链路追踪来记录请求在各个服务的调用情况方便排查问题和性能分析常用的链路追踪组件有ZipkinJaegerSkyWalkingPinpoint等等。
7. 日志收集分析
微服务服务多日志也分散在各个服务的机器上需要统一收集和分析日志常用的有ELK(Elasticsearch + Logstash + Kibana)EFKLoki等等。
8. 监控告警
微服务需要监控各个服务的运行状态性能指标等等出了问题及时告警常用的监控组件有Prometheus + GrafanaZabbix等等。
9. 容器和编排
微服务服务多部署复杂一般用Docker容器来打包部署用Kubernetes来编排管理容器实现自动化部署扩缩容自愈等等。
可以看到微服务需要很多配套的组件和工具才能很好地运行这也是微服务复杂度高的原因所以团队要有足够的能力和基础设施才能玩得转微服务。
六、服务拆分的原则
微服务最关键的一步就是服务拆分拆得好不好直接影响整个微服务架构的成败下面分享一些服务拆分的原则。
1. 单一职责
每个服务只负责一个功能或者一个业务领域不要一个服务负责太多功能不然就变成小单体了比如用户服务就只负责用户相关的功能不要把订单也放进来。
2. 高内聚低耦合
服务内部的功能要紧密相关内聚性高服务之间要尽量少依赖耦合性低修改一个服务尽量不影响其他服务。
3. 按业务领域拆分
服务拆分最好按业务领域来拆用DDD(领域驱动设计)的方法划分限界上下文每个限界上下文对应一个服务这样服务边界清晰符合业务逻辑。
4. 先粗后细
刚开始拆分的时候不要拆得太细先拆成几个比较大的服务然后随着业务发展再慢慢拆细拆得太细服务太多管理复杂反而不好。
5. 避免分布式事务
拆分的时候尽量把需要事务的功能放在同一个服务里避免跨服务的分布式事务因为分布式事务复杂性能差尽量用最终一致性来处理。
6. 数据独立
每个服务有自己的数据库不要多个服务共享一个数据库不然耦合性高服务之间通过API来获取数据不要直接查其他服务的数据库。
七、写在最后
微服务架构设计:从单体应用到分布式服务的演进。
微服务是一种很优秀的架构风格能解决单体应用的很多问题但是也不是银弹有很多挑战和复杂度不是所有项目都适合微服务小项目团队小功能简单单体应用更合适只有项目大了团队大了单体应用的问题很明显了团队也有足够的能力和基础设施了才考虑微服务。
而且微服务不是一步到位的是渐进式演进的先从单体开始随着业务发展再慢慢拆分微服务不要一开始就搞微服务那样复杂度太高容易失败。
这篇文章分享了单体应用的问题微服务的概念优势挑战技术栈服务拆分原则等等希望能帮大家更好地理解和设计微服务架构。
最后用一句话结尾:
"微服务不是银弹适合的才是最好的不要为了微服务而微服务要根据项目和团队的情况选择合适的架构。"
祝大家都能设计出合适的架构项目顺利!
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录