不用管服务器,也能扛住突发流量:用 FunctionGraph 搭一个带缓存与限流的 Serverless API

举报
yd_222894951 发表于 2026/11/12 14:18:02 2026/11/12
【摘要】 做个人项目或者小团队内部工具时,后端接口常常是最让人头疼的一环。买一台云服务器常年开着,平时没人访问也在花钱;流量一上来,单台服务器又容易被打垮;补丁、监控、备份、扩容,每一项都要自己盯。Serverless 的思路正好反过来:只在有请求的时候才运行代码,没有请求就不花钱,平台负责扩缩容。华为云的函数工作流 FunctionGraph 配合 API 网关 APIG,再加一层分布式缓存,就是一...

做个人项目或者小团队内部工具时,后端接口常常是最让人头疼的一环。买一台云服务器常年开着,平时没人访问也在花钱;流量一上来,单台服务器又容易被打垮;补丁、监控、备份、扩容,每一项都要自己盯。Serverless 的思路正好反过来:只在有请求的时候才运行代码,没有请求就不花钱,平台负责扩缩容。华为云的函数工作流 FunctionGraph 配合 API 网关 APIG,再加一层分布式缓存,就是一套很适合中小流量的后端组合。本文结合一次真实搭建过程,讲清楚缓存和限流这两个最容易翻车的地方。

一、先把架构画清楚:请求到底经过了哪几层

一个典型的请求链路是这样的:客户端先到达 API 网关,由网关做鉴权、限流和路由;网关把请求转发给 FunctionGraph 里的函数;函数先去分布式缓存 DCS 里查有没有现成结果,命中就直接返回;没命中再去算或者去数据库取,取到之后写回缓存,设置一个过期时间;最后把结果返回给客户端。云监控负责看调用量、错误率和耗时,日志服务负责留痕。

这样分层的好处是每一层只干一件事。网关管入口策略,函数管业务逻辑,缓存管热点数据,出了问题也好定位。千万不要把鉴权、限流、缓存、业务全塞进一个函数里,那样函数会越来越重,冷启动也越来越慢,改一处就可能影响全部。

二、写第一个函数:先跑通,再谈优化

函数入口一般是 handler(event, context) 这样的形式,event 里是网关传过来的请求信息,context 里是运行时的上下文。下面是一个简化后的 Python 示例,核心逻辑只有四步:解析参数、查缓存、回源计算、写缓存返回。

import json

def handler(event, context):
    body = json.loads(event.get("body") or "{}")
    user_id = body.get("user_id", "")
    if not user_id:
        return {"statusCode": 400, "body": json.dumps({"code": 400, "msg": "缺少 user_id"})}
    cache_key = "profile:" + user_id
    cached = get_from_cache(cache_key)
    if cached:
        return {"statusCode": 200, "body": cached}
    result = build_profile(user_id)
    payload = json.dumps(result, ensure_ascii=False)
    save_to_cache(cache_key, payload, ttl=300)
    return {"statusCode": 200, "body": payload}

这里有几个细节值得注意。第一,缓存键要带业务前缀,比如 profile:,不同业务不要共用一个键空间,否则清理缓存时会互相误伤。第二,返回体要统一成 JSON,网关侧的映射才好配。第三,函数里不要写死任何账号口令,连接缓存、数据库需要的凭据一律走环境变量或者平台委托,代码里只留占位符,提交代码之前再检查一遍。

第一次部署建议用最小的内存和超时配置跑通,再根据实际耗时慢慢调。函数能跑通之后,再用网关的测试功能调一次,确认网关到函数的链路是通的,然后再去加缓存和限流。一步到位同时改三层,出了问题很难定位。

三、缓存怎么做才稳:四个坑,逐个填

缓存能省下大量重复计算,但用不好反而会制造新故障。

第一个坑是缓存穿透。有人拿不存在的用户编号反复请求,缓存里没有,请求每次都打到数据库。办法是给空结果也缓存一个很短的时间,比如六十秒,并且在入口处先校验参数格式,不合法的请求直接返回,不进缓存也不进数据库。

第二个坑是缓存击穿。一个热点键刚好过期,同一瞬间几百个请求同时发现缓存是空的,一起去回源,数据库瞬间被压垮。常见做法有两种:热点数据用逻辑过期,缓存里存一份过期时间,读到快过期的数据时只放一个请求去刷新,其他请求继续用旧数据;或者在回源时加一把分布式锁,只允许一个请求去算,其他请求稍等片刻再读缓存。

第三个坑是缓存雪崩。大批键在同一时间过期,或者缓存服务整体重启,所有请求同时回源。办法是给过期时间加一个随机抖动,比如基础三百秒再加零到六十秒的随机数,让过期时间错开。平时也要给缓存服务留足内存水位,监控命中率和驱逐次数,命中率持续走低就要看是不是键设计出了问题。

第四个坑是一致性。数据改了,缓存还是旧的。最稳妥的顺序是先更新数据库,再删除缓存,而不是直接更新缓存。删除失败要有重试或者兜底清理机制。如果业务能接受短暂不一致,可以放宽要求;如果涉及金额、库存这类强一致场景,关键读操作要绕过缓存直接读库,不能为了快而牺牲正确性。

四、限流怎么做:网关和函数各守一层

限流的目标不是把用户挡在门外,而是保证系统在突发流量下不被拖垮。API 网关的流控策略可以按单个接口、按调用方、按时间段来设,比如某个查询接口每分钟最多接受六百次调用,超过就直接返回限流提示,不再往后转发。网关这一层限流的好处是请求还没进函数就被拦住了,函数不会被无意义的流量烧掉费用。

函数本身也要设一道防线,主要是并发数上限和超时时间。并发上限决定了同一时刻最多有多少个函数实例在跑,超时时间决定了单个请求最多占实例多久。两个值都要根据压测结果来定,不能拍脑袋。突发流量来的时候,宁可让一部分请求快速失败返回友好提示,也不要让所有请求都排队等到超时。

如果业务需要更精细的限流,比如按用户编号限流,可以在函数里用缓存做一个固定窗口计数器,思路是每个用户一个计数键,第一次访问设置过期时间,后续访问计数加一,超过阈值就拒绝。固定窗口在窗口交界处会有两倍流量的问题,流量再大一些可以用滑动窗口算法。限流的返回值要明确,告诉调用方什么时候可以重试,而不是直接断开连接。

五、冷启动和成本:先算账,再上线

函数第一次被调用或者长时间没人调用之后,平台需要重新准备运行环境,这个过程叫冷启动,表现为个别请求的耗时明显变长。缓解冷启动的办法有几条:保持函数包足够小,不要把用不上的依赖打进去;初始化阶段只做必要的事,数据库连接、缓存客户端这类重资源可以在函数外复用,不要每次调用都重建;对延迟敏感的核心接口,可以用预留实例保持少量实例常驻,代价是多花一点钱。

成本方面,函数按实际运行时间计费,内存配得越大,单位时间费用越高。很多人一上来就把内存和超时拉满,这是最浪费的做法。正确的做法是先按默认值跑,用监控看实际耗时和内存占用,再逐步下调到合理值。平时没流量的接口几乎不花钱,这正是 Serverless 适合个人项目和小工具的原因。成本监控要打开,设置一个费用告警阈值,避免配置失误导致账单失控。

六、联调和排错:先看日志,再怀疑代码

联调时最常见的问题有四类。第一类是超时,函数默认超时时间很短,调外部接口或者查数据库慢了就会超时,先在日志里确认是哪一步耗时最长,再决定是优化逻辑还是放宽超时。第二类是内存超限,通常是把大文件一次性读进内存导致的,改成流式处理或者分片处理。第三类是权限不足,函数访问其他云服务需要正确的委托和权限配置,缺什么补什么,不要图省事给过大权限。第四类是跨域问题,浏览器直接调接口会遇到跨域拦截,需要在网关侧正确配置跨域响应头。

排错的顺序应该是:先看云监控的调用量、错误数和耗时曲线,确认问题是偶发还是持续;再去看函数的运行日志,定位到具体的报错行;最后才是改代码。改完之后不要只测一次成功就上线,至少做一轮异常测试:缓存服务暂时不可用时函数能不能降级回源,数据库慢了会不会把函数拖垮,网关限流触发时返回是否友好。

七、上线前的检查清单

上线之前,对照下面这份清单过一遍:函数超时和内存是不是按压测结果设置的;缓存键有没有加业务前缀,过期时间有没有加随机抖动;限流策略是不是在网关和函数各配了一层;敏感信息是不是都放在环境变量或者委托里,代码和文章里有没有误贴真实口令;费用告警有没有打开;日志和监控能不能看到关键指标;降级方案有没有想清楚,缓存挂了能不能回源,数据库慢了会不会雪崩。

结语

Serverless 并不是不用管,而是把服务器的运维工作交给了平台,把精力留给业务逻辑本身。对个人项目和小团队来说,用 FunctionGraph 加 API 网关加分布式缓存搭一套后端,开发量小,成本可控,突发流量也有兜底。关键是把缓存和限流这两层想清楚:缓存要防穿透、防击穿、防雪崩,限流要分层、要快速失败、要给调用方明确的重试信号。这两层做扎实了,接口才能在没人管服务器的情况下,长期稳定地跑下去。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。