微服务不是银弹:大部分团队高估了自己的复杂度

博客分类: 

 

写在前面

 

前几天和一个创业公司的 CTO 聊天,他说他们团队 5 个后端开发,已经拆了 12 个微服务。我问他为什么要拆,他说"为了未来的扩展性"。然后我问他现在的 DAU 是多少,他说"几千"。

这让我想起很多年前见过的一个场景:一个刚起步的业务,还在验证商业模式,技术团队已经开始讨论服务网格和分布式追踪了。最后业务没做起来,技术架构倒是挺先进的。

微服务这几年被捧得太高了。很多团队在根本不需要的时候就开始拆服务,结果把自己搞得焦头烂额。今天想聊聊这个话题,不是说微服务不好,而是大部分团队真的不需要它,至少不是现在。

 

微服务的真实成本

 

 

开发成本的指数级增长

 

很多人以为微服务只是把代码拆开而已。实际上,从单体到微服务,你需要解决的问题是指数级增长的:

服务间通信:HTTP 调用、gRPC、消息队列,你得选一个。然后你会发现,本来一个本地函数调用,现在变成了网络请求。网络不可靠,你得处理超时、重试、熔断。原本简单的代码,现在要考虑各种边界情况。

分布式事务:这是最头疼的。单体应用里,数据库事务保证一致性。微服务里,你得用 Saga、TCC,或者干脆接受最终一致性。很多业务场景根本接受不了最终一致性,但架构已经拆了,只能硬着头皮上。

服务发现和负载均衡:本来一个进程内调用,现在要通过服务注册中心找到对方的地址。Consul、Eureka、Nacos,又是一堆技术选型要做。

监控和日志:单体应用打个日志就行,微服务里一个请求可能经过 5 个服务,你得把这些日志串起来。分布式追踪、链路监控,又是一堆基础设施要建。

我在金融业务里见过一个案例:一个理财产品购买流程,原本是一个单体应用里的几十行代码。拆成微服务后,涉及 3 个服务,每个服务都要做参数校验、权限检查、日志记录。原本 100 行代码能搞定的事情,现在要 500 行,而且出了问题排查起来特别费劲。

 

团队能力的隐性门槛

 

微服务对团队能力的要求远高于单体应用。这不是说团队技术水平不够,而是说你需要的技能栈和人员配置完全不同。

运维能力:单体应用部署一个包就行,微服务要部署几十个服务。没有成熟的 CI/CD 流程,没有容器化,没有自动化运维,你根本玩不转。

监控体系:单体应用看看日志和数据库就能定位问题。微服务里,你得有完整的监控体系:服务监控、链路追踪、日志聚合、告警系统。这些都需要投入人力去建设和维护。

开发规范:单体应用里,大家改同一份代码,很容易看到别人怎么写的。微服务里,每个服务都是独立的代码库,接口定义、错误处理、日志格式,全都要标准化。没有规范,很快就会一团乱。

很多团队在微服务化之前没想清楚这些问题,结果拆完之后才发现,运维成本增加了好几倍,开发效率反而下降了。

 

沟通成本的爆炸式增长

 

这是最容易被忽视的成本。康威定律说,系统架构会反映组织架构。反过来也成立,架构拆分会影响团队协作方式。

单体应用里,一个需求可能就是一个开发搞定。微服务里,可能涉及 3 个服务,需要 3 个开发协作。接口怎么定义?谁先开发?联调怎么做?每个环节都是沟通成本。

更麻烦的是,服务边界和团队边界往往不匹配。一个团队负责多个服务,或者一个服务横跨多个团队。这种情况下,任何改动都要跨团队协调,效率可想而知。

我见过一个极端案例:一个功能需求,在单体应用里 2 天就能上线。拆成微服务后,光是接口定义评审、联调时间安排、发布流程协调,就花了 2 周。

 

大部分团队不需要微服务

 

 

业务规模根本撑不起复杂度

 

很多团队拆微服务的理由是"为了未来的扩展性"。问题是,大部分创业公司根本活不到需要微服务的那一天。

我见过太多这样的故事:团队花了半年时间搞微服务架构,结果业务没起来,公司倒闭了。这半年时间如果用来快速迭代产品、验证商业模式,也许结果会不一样。

微服务是为了解决规模问题的。什么叫规模?淘宝、微信这种级别的才叫规模。日活几千、几万的业务,单体应用完全够用。即使日活百万,单体应用配合一些优化手段,也能撑住。

真实数据:我在金融业务中,见过单体应用支撑千万级用户的案例。关键不是架构有多先进,而是代码写得好不好、数据库设计合不合理、缓存用得对不对。

 

团队规模决定架构选择

 

微服务适合大团队,不适合小团队。这是康威定律的直接推论。

如果你的团队只有 5-10 个后端开发,单体应用是最优选择。大家在一个代码库里协作,改起来快,部署也简单。出了问题,随便找个人都能看懂代码,定位问题很快。

如果团队有 50 人,开始考虑微服务。但也不是无脑拆,而是按业务领域划分。订单、支付、用户,这种明确的边界,拆起来才有意义。

如果团队有 200 人,那微服务基本是必然选择。但这时候你面临的问题已经不是技术架构了,而是组织架构、沟通机制、技术治理。

大部分创业公司和中小团队,根本不在这个规模上。5 个人的团队搞 12 个微服务,只会把自己搞死。

 

技术债不是拆服务能解决的

 

很多团队拆微服务的另一个理由是"代码太乱了,重构不动,干脆拆开重写"。这是逃避问题,不是解决问题。

单体应用代码乱,是因为没有模块化、没有分层、没有规范。拆成微服务,这些问题依然存在,甚至更严重。因为现在你有 10 个代码乱的服务,而不是 1 个。

真正的解决办法是模块化设计。在单体应用内部做好分层:接口层、业务层、数据层。定义清晰的模块边界,用包管理工具强制依赖关系。这些做好了,代码一样可以很清晰。

而且,模块化单体是可以平滑演进到微服务的。当某个模块真的需要独立部署、独立扩展时,再拆出来。这比一开始就拆要稳妥得多。

 

什么时候才需要微服务

 

 

明确的拆分信号

 

不是说微服务不好,而是要在正确的时机做正确的事。以下几个信号,说明你可能需要考虑微服务了:

性能瓶颈:某个模块成为性能瓶颈,需要独立扩展。比如说,你的推荐系统计算量很大,但其他模块都很轻量,这时候把推荐系统拆出来单独部署,可以更灵活地分配资源。

团队协作瓶颈:团队规模超过 30 人,大家在同一个代码库里改代码,冲突频繁、发布困难。这时候按业务领域拆分服务,每个团队负责自己的服务,协作会顺畅很多。

技术栈异构:某些场景需要用不同的技术栈。比如说,核心业务用 Java,但推荐算法用 Python 更合适。这时候把推荐服务独立出来,用 Python 开发,通过 API 调用,是合理的选择。

发布频率差异:有些模块需要频繁迭代,有些模块很稳定。把频繁迭代的模块拆出来,可以降低发布风险,不影响稳定模块。

但即使有这些信号,也要谨慎评估。拆服务容易,合回去难。很多团队拆完才发现不合适,但已经骑虎难下了。

 

从模块化单体开始

 

我的建议是,永远从模块化单体开始。

在单体应用内部,做好分层和模块化。定义清晰的接口边界,每个模块只通过接口访问其他模块,不直接访问数据库。这样的设计,将来需要拆服务时,成本会低很多。

而且,模块化单体本身就能解决大部分问题。我见过很多团队,通过模块化改造,把原本混乱的代码变得清晰,开发效率反而提高了,根本不需要拆微服务。

关键是理念,不是形式。微服务的本质是职责分离、边界清晰。这些在单体应用里同样可以做到。

 

循序渐进的演进路径

 

如果确实需要微服务,也要循序渐进。不要一上来就全部拆开,而是:

1. 识别核心领域:哪些模块是业务核心?哪些模块相对独立?先拆独立的、非核心的模块,降低风险。

2. 建设基础设施:在拆服务之前,先把基础设施建好。服务发现、监控、日志、配置中心,这些都要有。没有基础设施就拆服务,是在玩火。

3. 一次拆一个:不要同时拆多个服务。一次拆一个,观察效果,发现问题及时调整。等第一个服务稳定运行了,再拆第二个。

4. 保持灵活性:如果发现拆得不合适,要敢于合并回去。很多团队碍于面子,明知道拆错了还硬撑着,结果越陷越深。

 

写在最后

 

微服务不是银弹,单体应用也不是原罪。技术选型的核心是匹配业务需求和团队能力。

大部分团队高估了自己的业务复杂度,低估了微服务的管理成本。结果在根本不需要的时候就开始拆服务,把自己搞得很累。

我的观点是:能用单体应用就用单体应用。做好模块化设计,控制好代码质量,单体应用可以走很远。等到真正遇到瓶颈了,再考虑微服务,那时候你会更清楚该怎么拆、拆什么。

技术架构不是炫技的舞台,而是服务业务的工具。最好的架构是刚刚够用,而不是过度设计。

最后送给所有纠结要不要搞微服务的团队一句话:如果你不确定要不要微服务,那就不要。等你确定需要的时候,你就知道该怎么做了。

You voted 4. Total votes: 33

添加新评论