去年深秋在徐庄软件园见客户,对方运维小哥顶着两个黑眼圈,把我们拉到机房边上的茶水间,说刚扛完上周的大促,原来的单体应用又崩了三次,每次都是全量宕机,客服电话被打爆,老板已经骂了三天。
当初拆微服务纯粹是被逼的
没人天生喜欢搞微服务。
那个客户的情况说起来真的典型。20多人的开发团队,所有业务都堆在一个Java war包里,商品、订单、库存、支付、用户、后台管理全挤在一起,改个商品列表的排序规则,要全量回归所有功能,光测试就要花三天。上次改优惠券的满减逻辑,不小心碰了支付回调的参数校验,直接导致两万多笔订单的支付状态没同步,最后赔了快十万。
大促的时候更惨。流量刚到平时的五倍,整个应用的内存直接打满,Tomcat的线程池堵死,所有接口全返回502,运维只能半夜爬起来重启应用,刚重启完没半小时,流量又冲上来,接着崩。

当时我们给的建议是先拆核心的高并发模块,不是上来就全量重构。毕竟谁都不想平白给自己加分布式事务、链路追踪、服务熔断的工作量。
别信那些’拆得越细越好’的鬼话
我见过太多团队,把微服务的拆分粒度当成了技术能力的证明。
上来就把一个普通的用户模块,拆成登录服务、注册服务、头像服务、积分服务、消息推送服务,恨不得连获取用户昵称的接口都单独搞一个服务。结果呢?一个简单的用户登录操作,要跨四五个服务调用,网络稍微抖一下,就超时失败。
我们当时给那个客户拆服务的时候,一开始也犯了这个错。把原来的订单模块,拆成了订单创建、订单查询、订单取消、订单退款四个独立服务。上线第一周,监控面板上的超时告警就没停过——一次退款操作,要先调订单服务查状态,再调库存服务回滚库存,最后调支付服务发起退款,任何一个环节出问题,整个流程就卡壳。
那段时间我天天泡在监控后台,咖啡喝到心悸,就差把告警铃声设成震动揣兜里了。
后来我们咬咬牙做了调整,把订单创建、取消、退款这些写操作,全合并回同一个订单服务,只把占了80%流量的订单查询接口拆成独立的只读服务。调整完之后,跨服务调用的次数直接减了六成,超时率瞬间降到了0.1%以下。
微服务拆分的粒度从来没有标准答案,唯一的判断标准,是你能不能hold住拆分后带来的运维复杂度。小团队没必要硬凑服务数量,能把核心的高并发模块拆出去,就已经解决了80%的问题。

落地前先把这几件事捋顺再动手

说实话,很多团队拆微服务拆到最后乱成一锅粥,根本不是技术不行,是一开始就没搞清楚前提。
先摸清楚业务的波动边界。哪些模块是真的扛不住流量?哪些是一年都改不了两次的稳定功能?像那个客户的后台管理系统,一年的迭代次数都不超过十次,完全没必要拆成独立服务,留在原来的单体里用着就行,平白多一套部署流程纯给自己找事。
基础组件要提前搭好。别拆完了才发现,连个统一的配置中心都没有,每个服务的参数改一次就要重新打包部署,出了问题连调用链路都查不到,只能靠工程师在群里@各个服务的负责人问情况。
我之前见过个10人不到的创业团队,上来就搞8个微服务,每个服务配一套独立数据库,光运维就招了3个,最后钱烧完了业务还没跑通,真的太蠢了。
责任要划清楚。每个服务必须有明确的owner,别拆完了出了bug,大家互相推,说这是别的组的服务,跟自己没关系。我们当时给客户定的规则是,哪个服务的告警响了,对应的owner必须在15分钟内响应,不然直接扣绩效。
哦对,还有,别想着一步到位。我们给那个客户拆服务,花了整整三个月,第一周只拆了商品详情的查询接口,跑了一周稳定了,才拆库存扣减的服务,接着是订单查询,最后才动支付相关的逻辑。要是上来就全量重构,指不定要出多少线上事故。
没人规定你的系统必须用微服务。
业务跑的稳,钱赚的到,比什么架构都强。