深入探寻微服务【第一篇微服务的坏】

引言:

在上一篇文章中我们一直在说微服务的好,可是我们也说了微服务不是银弹,它也有坏的地方,那究竟坏在哪儿,今天我们一起来看看。

微服务带来的挑战

到这里,如果你以为微服务就是"把大系统拆成小系统,一切变美好",那就大错特错了。微服务解决了一类问题,但引入了另一类更棘手的问题。有人说"微服务是分布式系统带来的复杂性",这句话说得非常精准。

下面我们来逐一剖析这些挑战。

服务发现的难题

在单体架构中,服务调用是方法调用------A模块调用B模块,直接import就行,B在内存里等着呢。

在微服务架构中,A服务要调用B服务,首先要知道B在哪里。但是B可能部署在10台不同的机器上,而且这些机器可能动态变化------扩容了、缩容了、某个实例挂了又被重启了。

问题来了:A服务怎么知道B服务的所有实例地址?可能你会说可以使用httpclient直接发请求,确实毛病,但是如果这个地址变了呢?我们就需要手动修改代码,这肯定不行。

这就引入了服务发现的需求。

解决方案通常有两种模式:

  • 客户端发现模式:A服务直接从注册中心(比如Eureka、Consul、Nacos)拉取B服务的实例列表,然后自己选择调用哪个。

  • 服务端发现模式:A服务把请求发给一个负载均衡器(比如Nginx、Kubernetes Service),由负载均衡器去查询注册中心并转发请求。

但无论哪种模式,都引入了一个新的组件------服务注册中心。这个组件本身必须高可用,如果注册中心挂了,整个系统可能就瘫痪了。这相当于把原来"不存在"的问题变成了一个需要专门维护的系统组件。

网络通信不可靠

单体架构中,方法调用是在同一个进程内,几乎是瞬时完成,而且不会失败(除非进程崩溃)。

微服务中,调用变成了跨网络的远程调用。网络是天生不可靠的:

  • 网络延迟可能比想象的大

  • 网络可能丢包

  • 对端服务可能暂时不可用

  • 对端服务可能处理超时

这些在分布式系统中被称为部分故障。部分故障是最棘手的,因为整个系统没有完全挂,但某些节点出了问题,你无法确定问题是暂时的还是永久的。

解决方案:引入了各种容错模式:

  • 超时控制:每次远程调用必须设置超时时间,不能无限等待

  • 重试机制:遇到可恢复的错误,自动重试(但要小心幂等性)

  • 断路器模式:当某个服务错误率超过阈值,自动"熔断",快速返回降级响应,避免连锁故障

  • 舱壁隔离:不同服务的线程池隔离,一个服务的故障不会耗尽所有资源

  • 降级:当依赖的服务不可用时,提供备选方案(比如返回缓存数据)

这些容错逻辑在单体架构中几乎不需要考虑,但在微服务中成了必修课。

分布式数据管理

这可能是我认为微服务中最难的问题。

在单体架构中,事务是简单的------多个表的更新在同一个数据库事务中完成,要么全部成功,要么全部回滚,ACID特性由数据库保证。

在微服务中,订单服务和库存服务使用各自的数据库。一个下单操作需要:

  1. 订单服务创建订单(在自己的数据库里)

  2. 库存服务扣减库存(在自己的数据库里)

  3. 支付服务发起支付(调用第三方)

这三个操作跨三个服务、跨三个数据库,如果第2步失败了,第1步怎么回滚?如果第3步超时了但实际支付成功了,怎么保证数据一致?

传统数据库事务已经无能为力了

这就引入了分布式系统中的一个经典问题:分布式事务

解决方案路径一:强一致性

使用两阶段提交(2PC)三阶段提交(3PC),或者使用支持分布式事务的框架(如Seata的AT模式)。这些方案试图在分布式环境下模拟ACID事务。

但代价是什么?性能急剧下降、可用性降低(因为要锁定资源)、实现复杂。

解决方案路径二:最终一致性

这是微服务社区更推崇的方向------放弃强一致性,接受最终一致性

核心思想是:不要求数据在任何时刻都一致,但保证在某一时刻之后数据会达成一致。

具体实现方式有:

  • MQ事务:订单服务创建订单后,发送一个"订单已创建"半消息,如果本地事务成功,那消费者就可以消费这条消息,如果失败那直接当没收到这条消息,rocketmq就可以做到。

  • 消息队列+本地事务表:订单服务在本地事务中同时写入业务数据和待发送消息,然后异步发送消息。库存服务消费消息进行处理。

  • Saga模式:将长事务拆分为一系列本地事务,每个步骤都有对应的补偿操作。如果某一步失败,执行所有已成功步骤的补偿操作。

最终一致性带来了显著的复杂性:需要处理消息的可靠投递、幂等消费、重试和死信等。这也是使用消息队列必须解决的问题,但从实践来看,这是微服务架构下处理数据一致性的主流方式。

分布式事务的CAP困局

说到分布式数据,必须要提CAP定理。这个定理是分布式系统的"基本法则":

  • C(Consistency,一致性):所有节点在同一时刻看到相同的数据

  • A(Availability,可用性):每个请求都能收到响应(但不保证数据最新)

  • P(Partition tolerance,分区容忍性):系统中部分节点之间通信失败时,系统仍能正常工作

CAP定理的核心结论是:在分布式系统中,当网络分区发生时,你必须在一致性和可用性之间二选一。

对微服务系统来说,网络分区是必然会发生的(网络不可能100%可靠),所以你必须在C和A之间做权衡。

  • 选择CP(一致性和分区容忍):当分区发生时,系统拒绝服务以保证数据一致。ZooKeeper、Eureka的某些模式属于这类。

  • 选择AP(可用性和分区容忍):当分区发生时,系统继续提供服务,但可能返回旧数据。Cassandra、Riak属于这类。

而更实际的场景是,对于不同的业务,我们可以做不同的选择:

  • 支付、库存扣减等对一致性要求高的场景,倾向于CP

  • 商品浏览、评论查询等对可用性要求高的场景,倾向于AP

这就是微服务架构带来的又一个复杂性维度------你需要在不同服务中做出不同的权衡,而不能再像单体数据库那样简单依赖ACID,而是需要我们自己设计好方案。

服务调用的依赖链与级联故障

单体架构中,调用链是线性的:A→B→C,如果C挂了,A和B能感知到错误,但影响范围可控。

微服务中,调用链可能非常深:服务A调用B,B调用C,C调用D,D调用E......任何一个服务出问题,上游所有服务都会受到影响。

更可怕的是级联故障------服务D响应变慢,导致服务C的线程池被占满,C变得不可用,进而导致B的线程池被占满,最终整个链路雪崩。

这就是前面提到的断路器、舱壁隔离、超时和限流等机制要解决的问题。

另外,复杂的调用链也给问题定位带来了巨大挑战。一个请求失败,可能是链路上任何一个服务出问题,也可能是网络问题,也可能是某个服务的依赖第三方出了问题。你需要能够在成千上万的调用中快速定位故障节点。

这催生了分布式链路追踪 (如Jaeger、Zipkin,skywalking)和可观测性体系(日志、指标、追踪三大支柱)的蓬勃发展。

运维的复杂性

部署一个微服务很简单,但部署50个甚至200个微服务呢?

每个服务有自己的配置、有自己的依赖环境、需要监控自己的健康状态、需要收集自己的日志......

在Kubernetes等容器编排技术成熟之前,运维微服务是一件极其痛苦的事情。即便有了K8s,你依然需要处理:

  • 配置管理:不同环境(开发、测试、生产)、不同服务的配置如何管理?

  • 日志聚合:一个请求跨越多个服务,日志散落在不同地方,如何关联?

  • 监控告警:几十上百个服务的CPU、内存、QPS、错误率如何统一监控?

  • 发布策略:灰度发布、金丝雀发布、蓝绿部署等如何实施?

这些催生了一整套云原生技术生态:Kubernetes、Prometheus、Grafana、ELK、Istio等等。

服务边界划分的难题

这是个更加"软性"但同样致命的问题:如何正确拆分微服务?

如果拆得太粗,还是像单体,发挥不出微服务的优势。

如果拆得太细,服务之间高频通信,网络开销巨大,系统变得脆弱复杂。

拆分边界如果设计错误,会导致:

  • 频繁的跨服务调用(性能差)

  • 分布式事务泛滥(数据一致性难)

  • 改一个功能需要改多个服务(发布耦合)

领域驱动设计(DDD)中的限界上下文 概念,是解决这个问题的重要工具。简单来说,就是找出业务中的天然边界------哪些功能经常一起变化,哪些数据有强一致性要求,哪些功能是独立的业务能力------把这些作为拆分的依据。

但这没有标准答案,需要架构师对业务有深刻理解,并且在演进过程中不断调整。

微服务与分布式系统的关系

到这里,我们其实已经触及了微服务和分布式系统的深层次关系。

微服务本质上是分布式系统的一种具体实现形态。

分布式系统是一个更宽泛的概念------只要多个计算机通过网络协作完成共同目标,就是分布式系统。Hadoop集群是分布式系统,数据库集群也是分布式系统。

而微服务是一种面向业务能力的分布式系统,它强调的是:

  1. 每个节点(服务)拥有独立的业务语义

  2. 每个节点可以独立演进

  3. 节点之间通过业务API通信,而不是底层RPC框架

换句话说,微服务 = 面向业务的分布式架构 + 一系列工程实践

理解这一点很重要,因为它意味着:所有分布式系统的经典问题,微服务都有;而微服务还额外带来了业务边界划分、团队组织架构等更深层的问题。

反过来看,学习微服务的过程,本质上就是在学习如何在分布式环境下构建和管理一个业务系统。这也是为什么微服务的学习曲线如此陡峭------你不仅要学业务设计,还要学网络、容错、数据一致性、运维等一整套分布式系统知识。

微服务技术生态全景图

为了让你对微服务有一个全局视野,我整理一下当前微服务技术生态的主要组成部分:

领域 解决的问题 代表技术
服务注册与发现 服务实例的动态感知 Nacos、Consul、Eureka、ZooKeeper
API网关 统一入口、路由、认证、限流 Spring Cloud Gateway、Kong、Nginx
配置管理 分布式配置的动态更新 Apollo、Nacos Config、Spring Cloud Config
远程调用 服务间通信 Dubbo、gRPC、OpenFeign
负载均衡 客户端侧的负载策略 Ribbon、Spring Cloud LoadBalancer
断路器/容错 故障隔离和降级 Resilience4j、Hystrix、Sentinel
分布式事务 跨服务数据一致性 Seata、TCC、Saga
消息队列 异步解耦、最终一致性 RocketMQ、Kafka、RabbitMQ
分布式链路追踪 请求链路跟踪 Jaeger、Zipkin、SkyWalking
可观测性 指标监控和告警 Prometheus+Grafana、Micrometer
日志聚合 集中日志管理 ELK Stack、Loki
容器编排 微服务的部署和管理 Kubernetes、Docker Swarm
服务网格 基础设施层下沉 Istio、Linkerd
CI/CD 持续集成和持续部署 Jenkins、GitLab CI、ArgoCD

这不是一个简单的技术列表,而是一个相互关联的生态系统。每项技术都在解决前面提到的某个具体挑战。

总结与思考

写到这里,我想做个总结。

微服务不是凭空产生的新概念,它是对单体架构困境的回应。它通过将系统拆分为多个可独立部署的服务,换取了灵活性、可扩展性和团队效率,但代价是必须面对分布式系统的全部复杂性

理解微服务的核心脉络可以用一句话贯穿:从单体到微服务,本质上是把"整体复杂性"拆解成了"个体简单性 + 连接复杂性"

  • 个体的简单性:每个服务代码量小、职责清晰、容易理解

  • 连接的复杂性:服务之间如何发现、通信、容错、保证数据一致

微服务成功与否,关键在于是否有一套成熟的基础设施和团队能力来支撑这个"连接复杂性"。

对于学习路径,我自己也在摸索当中不过ai给我的建议是:

  1. 先理解问题,再理解方案。不要一上来就学Spring Cloud或者Kubernetes,先把"为什么要这么设计"想清楚。

  2. 从一个小而完整的项目入手。实际编码会让你对"服务间调用"、"容错处理"、"分布式事务"有切身的体会,那种踩坑的体验是看文档无法替代的。

  3. 带着问题去学技术。比如学到断路器,先想想"如果没有断路器,系统会怎样?"再去了解Hystrix或Sentinel的实现原理。

  4. 保持演进思维。架构不是一次性设计出来的,而是随着业务发展不断演进的。不要追求一开始就拆出完美的微服务,允许自己从单体起步,逐步拆分,是更务实的做法。

下一篇,我会结合我的微服务项目,深入到代码和架构层面,把今天这些概念一个个落地------看看服务注册发现是怎么配的,分布式事务是怎么处理的,链路追踪是怎么做的。到那个时候,这些抽象的概念就会变得具体起来。

同时后续我还会写学习从零搭建一个agent的学习过程和收获,欢迎关注我与我一起探讨。

相关推荐
eric-sjq1 小时前
仅0.6B参数如何锁住超长记忆?Xiaothink-T17-RWKV5-MLA 架构深度解析:RWKV-v5 × MLA 的“降维打击“
python·架构
国科安芯1 小时前
抗辐照精密运放怎么选:ASL8522S 的斩波稳零与微安级功耗
架构·信息与通信·深空探测·抗辐射加固·极端环境电源
2401_8346369910 小时前
保姆级 Kubernetes 部署教程|从原理到三节点集群落地
云原生·容器·kubernetes
IT小白杨10 小时前
防关联用指纹浏览器还是虚拟机好?2026年技术架构深度对比与选型决策
chrome·经验分享·microsoft·架构·安全架构·指纹浏览器
2301_7807896611 小时前
DDoS 攻击溯源:DNS 水印标记 + 区块链存证的双保险
运维·服务器·网络·云原生·ddos
工业设备方案笔记15 小时前
RK3588 vs RK3568:AI边缘计算项目到底应该如何选择芯片平台?
arm开发·人工智能·目标跟踪·架构·边缘计算
一次旅行16 小时前
多智能体编排实战:拆解Plan-and-Execute范式+三层记忆架构,手写无依赖轻量Agent调度引擎
前端·javascript·架构
未来之窗软件服务16 小时前
商家自动化任务下一代架构混沌无界思维-东方仙盟
架构·自动化·仙盟创梦ide·东方仙盟·自动化任务
liangshanbo121517 小时前
Express SSE 流式输出实战:从入门 Demo 到 AI 生产级架构
人工智能·架构·express