相亲N次后,我用Spring Cloud把微服务整明白了

出色_创造者
2026-09-26 21:20
阅读 892

上周五晚上十一点,我还在成都天府三街的出租屋里对着电脑屏幕发呆。屏幕上是一个熟悉的红色报错:Connection refused: no further information。这已经是我第三次尝试把Redis集成进Spring Cloud项目里了,每次都是同一个坑。

我一个在成都拿着15k的程序员,相亲失败了七次才脱单。但就是这么一个“无趣”的人,硬是靠Spring Cloud从零开始搭了一套微服务,在公司站稳了脚跟。今天就把我踩过的坑、总结出来的最佳实践,像跟朋友聊天一样跟你们唠唠。

为什么非要上微服务

我在的公司是个做本地生活服务的小厂,原来一个单体应用,订单、用户、商品全塞在一个Spring Boot工程里。每次上线,运维小哥都要念一句“阿弥陀佛”,因为一个模块挂了,整个服务就崩了。

去年十一月中旬,公司接了个大客户,要求系统可用性达到99.9%。老板在周会上拍着桌子说:“咱们必须搞微服务!”最终我选了Spring Cloud Alibaba,原因很现实:Nacos比Eureka好维护,Sentinel比Hystrix配置简单,国内社区活跃,遇到问题好搜。

第一课:不是拆得越细越好

我犯的第一个错,就是把服务拆得太碎了。一口气拆了八个服务,16G内存的MacBook Pro直接风扇狂转,IDEA卡到怀疑人生。服务间调用链复杂到我自己都理不清。

后来我悟了:微服务拆分应该按业务边界来,而不是按技术模块来。 对于小团队,三个服务就够了:用户服务、订单服务、商品服务。支付和库存先合并进订单服务里,等业务复杂度上来了再拆。

判断标准:如果一个模块的代码量不到5000行,或者数据表和另一个模块强关联,就别拆。拆得越细,分布式事务、服务间通信、运维成本都指数级上升。

第二课:注册中心和配置中心,别省

很多新手直接写死IP地址调用。我一开始也这么干过,结果商品服务迁移到新服务器,订单服务还在调旧地址,线上订单全挂了。

后来我把所有服务都注册到Nacos,配置也全部托管到Nacos配置中心。改配置不用重新发版,服务自动刷新。这个体验真的爽,尤其是改Redis连接地址这种高频操作。

最佳实践:Nacos一定要部署集群模式,至少三个节点。 我刚开始用单机模式,结果Nacos挂了,所有服务互相找不到,整个系统瘫痪。改成三节点集群后,再也没出过这种问题。

第三课:Redis缓存,别乱用

我用Redis做了三件事:缓存热点数据、分布式锁、接口限流。

订单服务查询历史订单的接口,原来每次都查数据库,高峰期数据库CPU飙到90%。我加了Redis缓存,key设计成order:list:{userId},value存JSON序列化后的订单列表,过期时间30分钟。数据库压力降了70%。

但有个大坑:缓存穿透和缓存雪崩。 一次运营活动,大量用户同时查询同一个不存在的商品ID,请求全打到数据库上。后来加了两层防护:一是对不存在的ID也缓存空值,过期时间设短一点;二是用布隆过滤器在缓存前面拦一道。

缓存雪崩的解决:在基础过期时间上加上随机值,比如30分钟加随机0到5分钟。

第四课:服务间调用,别用RestTemplate硬调

一开始用RestTemplate直接调HTTP接口,每个调用点都要手动处理超时、重试、熔断,代码里全是try-catch。后来引入OpenFeign,声明式接口调用,代码量少了一半。

有个坑印象特别深:Feign默认超时时间太短。 商品服务数据库慢查询响应要5秒多,Feign默认超时1秒,订单服务直接抛异常。后来把Feign超时改成10秒,并加了重试机制。

最佳实践:Feign一定要配合Sentinel做熔断降级。 商品服务不可用时,订单服务直接降级返回默认值,保证核心流程不被拖垮。

第五课:分布式事务,能不用就不用

订单服务创建订单后,要调用库存服务扣库存,还要调用用户服务扣积分。一开始尝试Seata的AT模式,确实能实现强一致性,但性能损耗太大,全局锁阻塞其他事务,响应时间从200ms飙升到2秒。

后来换了个思路:用最终一致性替代强一致性。 订单创建后发送消息到RocketMQ,库存和积分服务消费消息各自处理。处理失败消息会重试,最终会一致,性能好很多。

关键点:发送消息和本地事务要在同一个事务里。 用了RocketMQ的事务消息,先发消息但不投递,等订单事务提交后再确认投递,避免订单成功但消息没发出的情况。

第六课:监控和日志,别等出问题才想起来

我吃过最大的亏就是没有做好监控。线上服务内存泄漏,隔几个小时OOM一次,每次都是用户投诉了才知道,手动重启。那段时间半夜被叫起来三次。

后来上了Spring Boot Admin做健康监控,配合Prometheus和Grafana做指标展示。内存使用率、GC频率、接口响应时间、错误率全可视化。配了Alertmanager,内存超过80%自动发钉钉告警。从此再也没被半夜叫起来过。

日志方面,引入SkyWalking做链路追踪,每个请求有全局traceId,界面能看到完整调用链,哪个环节慢了、报错了,一目了然。

第七课:关于TensorFlow,我想说几句

公司想在订单服务里加商品推荐功能。用TensorFlow训练协同过滤模型,部署成独立的Python服务,订单服务通过HTTP调用。Java这边不需要改太多代码。

最佳实践:AI模型服务应该独立部署,不要嵌在Java服务里。 Python和Java生态差异太大,混在一起维护成本极高。独立部署后可单独扩容、单独升级模型。

目前用Flask部署推荐服务,订单服务通过Feign调用,点击率提升了约15%。虽然离真正的智能推荐还差得远,但至少跑通了整个链路。

写到最后

回头看这一年多,从单体到微服务,中间踩了无数坑,也熬了无数个夜。但每次解决难题看到系统稳定运行,那种成就感让我觉得一切都值得。

今年秋招带了个实习生,他问我“微服务到底是什么”,我跟他说:“别急,先把一个服务跑起来,然后再想怎么拆、怎么调、怎么保证不出问题。一步一步来。”

其实微服务没有想象中那么难,也没有想象中那么简单。它需要你理解业务、熟悉中间件、掌握分布式理论。但最重要的是,你要有耐心,愿意去踩坑,愿意在踩坑之后总结经验。

最后送大家一句话:微服务不是银弹,但当你真正需要它的时候,它会是你最可靠的武器。

共勉。

评论 0

最热最新
暂无评论
出色_创造者Lv.1
0
影响力
0
文章
0
粉丝