单体架构的困局
很多老系统的开发者都经历过这样的场景:一个电商平台刚上线时,所有功能——用户登录、商品展示、订单处理、支付接口——全都塞在一个项目里。开发团队十几个人共用一个代码库,每次发个新功能,得等整个系统跑完一轮测试才能上线。改个按钮颜色,也得重启整套服务。高峰期一来,服务器直接卡死,排查问题像在迷宫里找出口。
这种结构就是典型的单体架构(Monolithic Architecture)。它在初期开发快、部署简单,但随着业务膨胀,维护成本越来越高。一个模块出问题,整个系统跟着瘫痪。这时候,拆分就成了必然选择。
垂直拆分:迈出第一步
为了解决单体臃肿的问题,不少公司开始做垂直切分。比如把用户管理、订单系统、库存服务各自独立成子系统,每个系统有自己的数据库和接口。这时候,团队可以按业务线分工,互不干扰。用户组改密码逻辑,不影响订单组发版。
但这种拆法还是有局限。各个系统之间靠HTTP或者RPC调用,一旦某个服务响应慢,连锁反应就会出现。比如下单时查不到库存,页面就一直转圈。而且数据库各自为政,数据一致性难保证,半夜跑个对账脚本成了家常便饭。
服务化起步:引入中间件
当服务数量多了,手动维护调用关系变得不可持续。于是注册中心开始上场。Dubbo、Zookeeper这类工具让服务能自动注册和发现。订单服务启动后,自己告诉注册中心“我在192.168.1.10:20880”,支付服务需要调它时,直接去问注册中心就行。
同时,配置管理中心也派上了用场。以前改个超时时间要重新打包发布,现在通过Apollo或Nacos,在网页上点几下就能生效。运维人员终于不用半夜爬起来改配置文件了。
容器化与编排时代
服务越拆越多,部署成了新难题。几十个微服务,每个都有不同资源需求,传统物理机或虚拟机管理起来太累。Docker的出现改变了这一点。把每个服务打包成镜像,运行环境统一,移植性大大增强。
光有容器还不够,怎么调度、扩容、自愈?Kubernetes成了关键角色。定义好Deployment配置,告诉集群“我要三个订单服务实例”,K8s自动拉起Pod,分配网络,健康检查失败还会自动重启。凌晨三点流量突增,HPA(水平伸缩)策略触发,瞬间扩容两倍实例,等高峰过去再缩回去。
服务网格的精细化治理
当调用链越来越复杂,传统的熔断、限流逻辑嵌在代码里,维护困难。Istio这类服务网格技术开始被采用。通过Sidecar模式,把通信控制从应用中剥离出来。
比如想对支付服务做灰度发布,可以在Istio里设置规则:先把5%的流量导向新版本,观察日志和指标没问题,再逐步提升比例。这个过程完全不用动一行业务代码。
apiVersion: networking.istio.io/v1alpha3\nkind: VirtualService\nmetadata:\n name: payment-route\nspec:\n hosts:\n - payment-service\n http:\n - route:\n - destination:\n host: payment-service\n subset: v1\n weight: 95\n - destination:\n host: payment-service\n subset: v2\n weight: 5向云原生演进
现在的趋势是往云原生走。微服务不再只是拆分,而是围绕可观测性、弹性、自动化来设计。Prometheus收集指标,Jaeger跟踪请求链路,ELK集中日志。故障发生时,运维能在Grafana看板上一眼看出瓶颈在哪。
Serverless也在渗透进来。某些低频任务,比如生成月度报表,直接用函数计算实现。不用长期占用实例资源,按执行次数计费,成本更低。微服务的边界因此变得更灵活,有些功能甚至不再需要“服务”形态。
这个演进过程没有终点。每家公司根据自身规模和技术积累,走在不同的阶段。有人还在从单体向微服务过渡,有人已经用Service Mesh支撑上千个服务实例。变的是技术栈,不变的是对稳定性、可维护性和快速交付的追求。