前情
每个月最怕看到云账单。
好几台2核4G的机器,CPU常年跑在5%以下,内存倒是占了快2个G,一个月三四百块钱就这么白白烧掉。我跟运维说,要不换更便宜的机型?运维说换了也差不多,这点负载,再便宜的机器也是浪费。
后来我想明白了,问题根本不在机器贵不贵,在于我们养了一堆“闲人”。于是我开始带着团队做减法,按下面这四步走,难度从低到高,省下的钱却一次比一次狠。
正文
第一步,先给Java进程“节食”。
很多低流量服务,我们上来就给它配2G堆内存,纯属过度喂养。我挑了一个边缘服务做实验,直接把-Xmx从2G压到256M,垃圾回收器换成SerialGC,顺手把机器配置也降成1核1G。压测跑了一遍,QPS没掉,响应时间也没明显变长。观察了一周,一次Full GC都没有。
于是我让团队把所有类似服务都照此处理,逐步分批的将机器配置一降,月费直接砍半。这是代价最小、见效最快的一招,改几行参数的事,但大部分人都没想过去做。
第二步,给低流量服务“找室友”。
公司内部的管理后台、报表小工具、某某数据同步程序,一天撑死几十个请求,居然独占一台机器,这跟一个人住一栋别墅有什么区别?我把它们全迁到同一台8核16G的服务器上,用Nginx按端口转发,每个服务严格限制-Xmx,防止一个OOM把全宿舍炸了。用systemd做进程守护,加了个简单的存活监控脚本,完事。
这一轮下来,直接关掉了五台僵尸机,账单瞬间清爽不少。
第三步,把传统Jar包搬上Serverless,低峰期不再白烧钱。
前两步做完,机器合并得差不多了,但翻翻还有一堆定时任务和低频接口——每天夜里跑几分钟的数据同步、偶尔被调一次的webhook、几个星期才有人用的内部小工具。就为了这点活,还得养着机器24小时待命,典型的“交着整租的钱,用着钟点房的量”。
以前我对Serverless的理解就是函数计算,得把Spring Boot那套全拆了重写,想想就劝退。后来团队一个小伙子在技术群里看到有人分享阿里云的Serverless SAE,说现在有些云原生产品能直接跑原生jar包,Spring Boot应用不用改造就能享受弹性伸缩,我才知道路子没那么窄。
我挑了一个每天凌晨3点跑的数据对账程序当小白鼠,典型的Spring Boot单体,打成一个fat jar,原来独占一台2核4G的机器,实际每天只干5分钟的活。迁移过程简单得出乎意料——jar包拖上去,选好Java运行环境,配好内存规格,几分钟就跑起来了,一行代码没改。
真正的改进在于伸缩策略。以前这台机器24小时开着,白天完全没人用,CPU在那儿空转。现在我把应用配置成动态扩缩容——高峰期自动弹到多个实例扛流量,低峰期只保留1个实例兜底。别小看这“保留1个”而不是“缩到零”,这是我踩过坑才总结出来的。缩到零虽然更省钱,但请求来的时候冷启动要等好几秒,偶尔哪个业务方半夜查个数据,等半天页面打不开,第二天投诉就来了。留1个实例在那,响应速度跟常驻机器没区别,用户体验不受影响,但跟原来开好几台机器相比,成本已经降了七八成。
这里有两个配置细节一定要做好,不然就容易翻车。
一个是健康检查
你得确保新弹出的实例真正就绪了才能接流量。别一启动就往里打请求,结果Spring容器还没初始化完,接口调了半天返回500,那还不如不弹。我配了Readiness探针,等上下文加载完、数据库连接池初始化好了,才把流量切过来。
另一个是优雅停机
缩容的时候别直接把进程杀掉,得给正在处理的请求一点时间收尾。我配了30秒的terminationGracePeriod,收到缩容信号后先摘掉流量,等手里这批请求处理完再退出,业务方完全无感。
那个对账程序原来独占一台机器,一个月将近三百块。换成弹性伸缩后,低峰期只剩1个小规格实例,高峰期自动弹,月底一算账,月费掉到了几十块。我把类似场景全梳理了一遍,挨个改造成动态扩缩容,原来养这些“夜间值班员”的固定开销,变成了按实际用量弹性的成本。
这一步比前两步门槛略高——需要花时间分析业务流量规律来定伸缩阈值,需要把健康检查和优雅停机配到位。但一旦跑通一个,后面的复制成本几乎为零,而且因为留了1个实例保底,业务方完全感觉不到变化,你默默把钱省了,零投诉。
第四步,敢把微服务“合回去”。
这是最需要勇气的一步。我们有两个服务,从来都是一起改一起发,QPS加起来还不到10,硬生生拆成了两个微服务,调用链路多了一截,排错麻烦了一倍。我跟团队说,别撑了,合。
用Maven子模块把两个服务变成同一个项目里的不同package,内部直接调用,一下子砍掉了远程序列化开销和那套服务治理组件。不仅省了机器,还省下了维护这套分布式系统的心智负担,开发效率反而高了。
结尾
这四步走完,我们云账单降了六成多。有意思的是,系统没变慢,稳定性也没下降,反而因为架构变简单了,出问题的概率更小。
回头想想,真是验证了一句老话,“合久必分分久必合”。
我们花了很多年把服务拆开,又花了不少精力把它们合回去。但这不是倒退,是知道什么东西值得拆,什么东西该老实待在一起。降本的尽头不是往云上堆更多花活,而是敢于把不该有的东西“下”掉。