
简介围绕Serverless技术开发实战这份PPT以分布式Puppeteer网页截图服务为贯穿案例系统讲解函数计算的核心原理、实时弹性伸缩机制以及“无需管理基础设施”的免运维优势定位为面向云端开发者与架构师的解决方案型学习材料。内容依次涵盖函数计算概述、Web应用迁移体验、部署Puppeteer截图服务并延伸至Rendertron搭建Headless Chrome渲染方案其中穿插yarn dev、fun deploy等常用命令清晰呈现从传统部署到Serverless平台的迁移路径与要点尤其适合需要处理JavaScript渲染依赖、SEO优化或移动端截图预览场景的团队。包体为单个PPTX文件大小约3.42MB文件数量精简但知识密度较高既可用于个人快速学习也适合团队内部技术分享。已有152人学习可借助PPT了解如何在函数计算上按需运行浏览器截图任务理解按实际调用计费的成本模型并结合实时弹性伸缩能力实现资源利用与高可用的平衡从而掌握低成本、高弹性的服务部署思路为后续实践Serverless架构提供扎实参考。1. 为什么都在聊Serverless运维焦虑和成本焦虑的另一种解法三年前我为公司部署一个定时报表任务申请了一台4核8G的服务器。任务每天跑20分钟剩下23小时40分钟机器都在闲置但账单一分不少。后来换成Serverless部署同样的任务改成事件触发月底成本降到原来的零头运维侧几乎不再为它熬夜。这件事让我真正意识到Serverless并不是什么云端黑科技而是把「为闲置付费」变成「为使用付费」的算力分配方式。这个标题指向的开发实战核心就是解决两件事第一怎么把业务从传统服务器迁移到Serverless架构第二迁移之后怎么保证线上稳定、账单可控、排查不抓瞎。适合正在被服务器运维缠住、或者想在新项目里直接采用Serverless部署的团队。本文不讲空泛的架构理念直接拆解选型依据、部署路径、关键参数和线上踩坑记录让新手能照做让熟手能避开我走过的弯路。2. Serverless选型前的四个问题搞懂它再动手比急着部署更重要很多团队一听到Serverless就急着把业务往函数计算里塞结果遇到冷启动超时、连接池耗尽、账单翻倍又骂着迁回去。选型阶段花两个小时想清楚边界比上线后花两天回滚划算。2.1 无服务器不等于没有服务器架构边界要画清楚Serverless的命名很容易让人误以为物理机消失了。实际上服务器还在只是它的生命周期被平台接管开发者不再关心机器在哪、配置多少、什么时候扩容。你交付的是一段函数代码平台负责拉起运行环境、执行代码、回收资源。这个特性决定了架构的边界有状态的东西不适合进来。Session、本地文件缓存、内存队列、长连接这些依赖「机器记忆」的业务放到Serverless里会反复撞墙。常见做法是把状态外置到Redis或数据库把函数设计成无状态执行单元。函数只做三件事——接收事件、处理数据、返回结果其他一概不碰。这里要区分两个概念函数计算和Serverless容器。函数计算粒度更细按调用次数计费适合API后端、消息处理、定时任务Serverless容器则承载体量更大的服务适合微服务迁移。标题里的开发实战我默认以函数计算为主线因为它是入门成本和返工风险最低的切入点。2.2 冷启动、计费粒度、并发上限三个决定成本的底层概念冷启动是函数实例从零到可用的过程。平台需要下载代码包、拉起运行环境、初始化运行时这个耗时通常在几百毫秒到几秒之间。用户的第一个请求往往要承受这个延迟这是Serverless最被诟病的地方也是选型时必须想清楚的硬约束。计费粒度决定了你的账单长什么样。传统服务器按小时计费Serverless按调用次数加资源使用时长计费资源时长精确到毫秒级别。这意味着一个每天被调用10万次、平均执行50毫秒的函数和一个每天被调用100次、平均执行5秒的函数账单逻辑完全不同。前者适合Serverless后者要考虑常驻实例。并发上限是压垮系统的暗坑。每个函数实例能同时处理的请求数是有限的超出部分要么排队要么报错。很多团队在测试环境跑通就上线结果大促流量一来平台疯狂扩容数据库连接池被瞬间打满整个链路雪崩。选型阶段就要确定你的峰值QPS是多少单实例并发是多少允许的最大实例数是多少。2.3 什么业务适合Serverless什么业务该绕开适合的业务有一个共性流量呈脉冲状且对冷启动容忍度较高。我整理过一张清单真实项目里直接照着对照即可API网关后端请求天然无状态弹性扩缩容是刚需定时任务与批处理短时执行完就释放不存在闲置成本消息队列消费者事件驱动模型与Serverless天然契合图片处理、视频转码单次任务CPU密集并发不高但突发性强运维自动化脚本执行频率低、逻辑独立完全没必要养一台常驻机器不适合的也列清楚别硬上。WebSocket长连接服务、实时游戏对战、需要GPU训练的AI任务、强状态业务购物车、在线编辑这些在Serverless上要么实现成本极高要么性能不达标。另外一个特殊情况当你的业务已经是全天候均匀流量时Serverless省下的运维成本可能被账单差异抵消这时候用容器服务反而更划算。2.4 一份可以照着勾的选型对照表表格不是用来收藏的是动手前逐条打勾的。能打勾超过六条就可以推进Serverless部署少于四条建议重新评估。评估维度关键问题适合Serverless的答案流量模式流量是否集中在特定时段是有明显的波峰波谷请求时长单次请求平均执行时间多少小于5秒最好小于1秒状态依赖业务是否依赖本地内存/磁盘不依赖状态都在外部存储冷启动容忍用户能接受偶尔几百毫秒的首次延迟吗能或通过预置实例解决团队运维力是否有人力维护服务器和K8s集群没有希望平台托管成本模型现有服务器利用率是否很低是日常CPU使用率低于10%事件源类型业务是否由API、消息、定时器触发是符合事件驱动模型迁移复杂度现有代码依赖系统本地环境吗无特殊依赖或能用容器镜像打包3. 第一个Serverless服务怎么落地三条部署路径与校验清单选型通过之后就是动手。这一章给出三条可执行的部署路径按团队情况任选其一。三条路径不是互斥关系很多团队第一阶段用控制台成熟后切到命令行或容器镜像。3.1 控制台手动创建适合第一次跑通全流程第一次接触Serverless别急着写脚本。打开云厂商的函数计算控制台选择空白模板或HTTP函数模板手动创建一个Hello World函数。这个过程花五分钟但能让你直观理解函数的三要素触发方式、运行时、入口方法。创建页面通常会让你配置四个东西函数名称、运行时环境Python/Node.js/Java/Go等、内存大小、超时时间。第一次演练就选最小的内存配置超时时间设3秒。创建完点击测试按钮平台会模拟一次事件调用并返回执行结果。这里注意看两个输出执行日志和返回内容。日志里能看到实例启动耗时和实际执行耗时这两个数据就是后续调优的依据。控制台路径的意义不在于生产可用而是建立心智模型。很多教程直接教写代码反而让新手忽略了一个基本认知Serverless函数的运行环境是平台管理的你看到的控制台页面就是整个运行时的全部后续所有自动化操作都是在模拟你在页面上做的这些动作。3.2 命令行CLI部署把环境写进代码环境差异交给平台当函数数量超过三个控制台的操作效率就跟不上了。这时候迁到命令行工具。主流云厂商都提供各自的CLI核心流程大同小异初始化项目、编写函数代码、配置部署参数、执行部署命令。以常见的Serverless CLI工具为例部署一个Python函数的典型命令如下# 初始化项目目录--template指定运行时模板 serverless init --template python3 --name order-handler # 进入项目目录 cd order-handler # 部署函数--memory指定内存MB--timeout指定超时秒数 serverless deploy --memory 512 --timeout 10 --region cn-north-1命令背后的逻辑要清楚。init命令拉取的是一个标准项目骨架里面包含函数入口文件、依赖声明文件和资源配置文件。deploy命令做的事情是把本地代码打包上传到平台、根据配置创建或更新函数、绑定触发器。--memory和--timeout是部署时写入函数配置的之后可以在控制台修改但推荐把配置固化在文件里这样每次部署都是可预期的。参数说明内存配置直接决定CPU分配和计费单价512M是通用起步值适合大部分IO密集型业务--timeout是对单次请求执行时长的硬上限超过就强制终止10秒对HTTP请求偏宽松对消息处理差不多--region要按业务所在区域选择跨区域调用会增加固定延迟这点常被忽略。部署完成后CLI会输出一个函数URL。拿着这个URL用curl测一下curl -X POST https://your-function-url/execute \ -H Content-Type: application/json \ -d {orderId: 10001}正常返回JSON结果就说明链路通了。这里要强调一个习惯每次部署前把本地依赖安装好很多函数部署失败都源自依赖没打进去。3.3 容器镜像托管解决依赖难缠时的最后一公里Python项目里native依赖、Java项目的JAR包冲突、Node.js项目的node_modules体积经常导致函数代码包超过平台限制或部署后启动失败。这时候容器镜像托管是后悔药——把你熟悉的Dockerfile写出来构建成镜像平台直接拉取运行。Serverless容器与自建K8s的区别在于你不用管节点池、不用管负载均衡平台根据请求自动拉起和销毁实例。具体做法是在项目根目录写Dockerfile# 基于官方运行时镜像 FROM python:3.11-slim # 设置工作目录 WORKDIR /app # 复制依赖声明文件并安装 COPY requirements.txt . RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple # 复制业务代码 COPY . . # 声明服务端口 EXPOSE 8080 # 启动入口 CMD [python, app.py]构建镜像并推送到镜像仓库然后在Serverless控制台创建函数时选择「容器镜像」方式填上镜像地址和启动命令。平台对镜像是按需拉取的但首次拉取耗时取决于镜像大小所以镜像要精简。常见做法是用slim基础镜像、分阶段构建把构建依赖和运行依赖分开、清理pip缓存把镜像压在200M以内。这条路径适合两类场景一类是函数依赖了特定版本的底层库比如OpenCV、FFmpeg另一类是团队已有成熟的容器化交付流程不想为Serverless单独改造。代价是镜像冷启动比代码包方式更慢需要通过预置实例或最小化镜像来缓解。3.4 部署之后先别急着写业务五步校验清单很多项目上线后出问题不是因为代码bug而是部署配置与预期不符。我养成一个习惯任何函数部署完先跑这套校验清单第一步看日志控制台或CLI查看最近一次调用的日志确认实例启动耗时和执行耗时冷启动是否在容忍范围内第二步看返回头用curl -I访问函数URL检查HTTP状态码和响应头里的Server字段确认请求确实打到了函数计算而不是其他网关第三步改配置验证把内存调大一档再调用一次观察执行时间的变化验证资源配置和性能的关系第四步测超时行为制造一个必然超时的请求确认平台返回超时错误、并查看日志中是否记录强制终止第五步看监控图进入函数监控页面确认调用次数、错误次数、平均耗时三个指标都在正常范围这套清单跑完函数才算真正「活」了。很多人跳过前三步直接写业务逻辑结果线上环境变量与本地不一致排查到半夜最后发现是平台默认的环境变量覆盖了业务配置。4. 内存、并发与超时线上表现靠这三个参数说话Serverless部署最核心的策略都集中在三个参数上内存、并发度、超时时间。这三个参数直接决定成本、性能和稳定性也是线上调优的主战场。4.1 内存与CPU绑定选配置其实在选账单平台的内存和CPU是线性绑定的内存配得越高CPU份额越强。例如一个函数配128M内存和配512M内存后者的CPU算力往往翻倍甚至更高。这意味着很多执行的瓶颈可以用内存配置来调节而不是只盯着超时时间。这里有一个常见的账单误区以为把内存配小就省钱。账要这样算——假设函数每次执行需要100ms配128M时因为CPU弱要跑200ms而配512M时跑100ms。后者的单位资源单价贵约4倍但执行时间减半总价可能持平甚至更便宜。所以内存选择要基于函数类型IO密集型的配小内存足够CPU密集型的配大内存反而省钱。实际调参的方法是压测而不是拍脑袋。先用128M部署用压测工具发100个并发请求看平均耗时和错误率。如果失败率高且CPU资源已经跑满说明内存给少了翻倍配置再测。如果单次执行耗时大于300ms也要考虑升配。这个过程的产出是一张「内存-耗时-成本」对照表后续每次业务量变化都能快速决定要不要调。4.2 并发度与实例数上限成本黑洞最容易藏在这里函数计算的并发模型是每个实例同时处理一个或几个请求取决于运行时并发请求数超过单实例能力时平台会创建新实例直到达到你设置的实例数上限。这个上限如果没设置默认值可能很高流量突增时账单会失控。成本黑洞的典型场景是这样的业务峰值QPS只有200但因为一段循环逻辑没优化单请求耗时2秒单实例并发为1平台就需要拉起200个实例。按每个实例512M计价这一小时的费用是账面数字的好几倍。解决办法有两个方向一个是优化代码降低耗时另一个是显式设置实例数上限比如最多20个实例多余请求排队等待。设置排队要谨慎。有些平台对超时请求直接丢弃不会帮你排队用户侧表现为请求失败。所以要配合消息队列使用先把请求写入队列函数从队列拉取消费削峰填谷。这也是Serverless部署里最推荐的生产模式——异步化改造。同步调用虽然开发简单但扛不住流量尖峰。4.3 超时时间与重试策略Serverless下的失败处理逻辑传统服务器里接口跑太久只是慢不会被杀掉。函数计算里超时是硬约束时间一到平台立刻终止执行而且可能已经释放资源。这就带来一个诡异现象函数日志里看不到业务错误执行记录却显示失败因为进程是被外部杀掉的。超时时间设置没有标准答案要区分同步链路和异步链路。同步API网关触发的函数建议15秒以内尽量把耗时压在500毫秒内超时的请求让客户端重试。异步消息触发的函数可以放宽到5分钟因为消息还在队列里函数被杀死后可以重新投递。定时任务类函数最宽松常见做法是设10到15分钟给足跑批时间。重试策略是另一个容易翻车的点。平台默认会对失败调用进行重试但重试是叠加的——你的函数处理消息时调用了下游API下游超时了平台重试你的函数函数又调下游API下游还没恢复又来一次。这是典型的重试风暴。解决思路是函数内部不设置无限重试下游调用设置快速失败同时开启平台的重试退避策略让多次重试之间有时间间隔。4.4 中小团队起步参数速查表这是一份经过真实项目验证的起步配置适合中小团队在低并发场景下快速上线后续按压测结果调整。函数类型内存配置超时时间实例数上限触发方式HTTP API函数512M10秒20API网关消息队列消费函数256M3分钟10队列触发器定时任务函数1024M15分钟5定时触发器图片处理函数1024M30秒10对象存储触发器轻量工具函数128M5秒2手动/CLI调用这个表格的价值是消除「第一次配多少」的选择恐惧。后续调优的原则是先保证功能正确再调性能最后优化成本。很多人一上来就按最大配置跑账单出来才后悔没看参数表。5. Serverless部署避坑指南五条线上事故换来的经验以下每一条都是实际踩过的坑。写成「现象-原因-解决」的格式方便出了类似问题时对号入座。这不是什么玄学都是可以用日志和监控确认的。5.1 现象函数返回成功数据却丢了线上API返回200前端也提示操作成功但后台数据库查不到这条记录。排查发现日志里函数执行正常没有异常堆栈返回结果也是一段符合预期的JSON。最后定位到问题出在异步调用代码里调用了另一个函数采用的是异步方式主函数不等子函数执行完就返回了。子函数执行失败时主函数感知不到所以对外表现是成功的。原因是对事件驱动的理解有偏差。异步调用不比同步调用可靠它只负责把事件投递给目标函数不保证目标函数执行成功。解决方式是在异步调用代码里补充回调逻辑或者把主函数的返回值改为依赖子函数的执行结果。最稳妥的方案是把这种依赖关系从代码层面改造成消息队列主函数把任务写入队列子函数消费完成后再写一条结果记录主函数通过查询结果记录判断成功与否。5.2 现象日志全丢了排查无从下手某次线上故障处理打开日志平台查函数日志发现只看到最近几条更早的全是空白。反复确认不是权限问题日志确实没有采集到。最后发现是日志平台的采集配置只覆盖了默认日志流函数代码里往标准输出打印的内容没有被收集因为运行时环境配置的日志项目ID和采集器不一致。原因是在创建函数时选了默认日志配置但函数代码里通过第三方日志库写入的日志文件不在标准输出里。解决方式是调整日志输出策略统一让所有日志走标准输出让平台日志系统接管采集而不是自己写文件。如果框架强制写文件需要在函数配置里加上日志挂载路径把日志目录指向平台可采集的位置。另一个常见做法是在代码入口处加一个logging配置强制所有logger输出到stdout。5.3 现象数据库连接被函数实例耗光这是Serverless最典型的翻车现场。函数每次调用都新建数据库连接没有使用连接池或者连接池设在了全局变量里但实例频繁被销毁重建导致连接无法复用。线上表现为数据库实例的连接数达到上限新的函数调用全部报too many connections。原因在于传统服务器的连接池是长生命周期的函数计算的实例生命周期不确定空闲时会被平台回收。如果连接池只存在实例内每次冷启动都会重建。解决方式是使用外部连接池服务或选择云数据库的Serverless版本支持自动扩缩连接数。代码层面的缓解方案是设置合理的连接空闲回收时间确保实例销毁前释放连接但这治标不治本流量大了还是会把数据库打满。根本解法是控制函数实例并发数让数据库连接数等于实例数上限乘以每实例连接数。5.4 现象定时任务同一时刻触发了多次监控发现定时任务在某个整点被触发了六次业务数据被重复处理。排查发现函数绑定了多个触发器一个是控制台配置的定时触发一个是代码里通过API动态注册的定时触发还有一个是项目初始化脚本里重复执行注册操作导致的重复规则。原因是触发器注册操作没有被设计成幂等。同一份部署脚本跑了多次平台上的定时规则就存在多个都在同一个时间点触发同一个函数。解决方式是部署前先检查是否已存在同名的定时触发器存在则先删除再创建。另一个思路是把定时任务的幂等性放在业务代码里用Redis setnx加分布式锁锁的key携带任务周期只有抢到锁的实例才执行任务锁过期时间要大于任务最长执行时间。5.5 现象代码本地正常上云就超时本地跑函数一切正常输出秒回部署到Serverless平台后常常等到超时时间耗尽才返回。查日志发现耗时全花在了一个下游HTTP调用上本地访问这个下游服务只要50毫秒线上访问需要3秒以上。原因是函数所在的环境网络路由与本地不同可能访问公网需要经过NAT网关或者访问同区域内部服务时走了公网出网链路。解决方式是在函数的VPC配置里把目标服务的内网地址加入VPC内访问函数直接通过内网IP调用绕开公网路由。另一个隐蔽原因是DNS解析慢函数实例里访问外部服务时DNS解析耗时远高于本地因为平台默认的DNS配置不适合高频调用需要在代码里使用连接复用和IP直连策略。6. 把排查效率提上去我的调试验证三板斧Serverless部署最痛苦的不是写代码而是出了问题不知道从哪里查。传统服务器的ssh登录进去看函数计算只能靠日志和链路追踪。我用了很长时间才形成一套适合自己的排查方法论分享出来供参考。第一板斧结构化日志替代print。早期调试函数习惯写print日志平台采集到的是一堆没有上下文的字符串。后来统一改为JSON格式输出每次请求把所有关键信息打包requestId、函数名、业务参数、耗时、下游调用结果。这样日志平台检索时可以直接按requestId过滤整条链路。配合日志平台的键值索引查询效率提升几个量级。这项改造需要写一个日志工具类在函数入口处统一初始化业务代码全部通过工具类打日志禁止裸用print。第二板斧本地模拟网关事件把线上问题搬回笔记本。每次线上出问题我第一件事不是去改代码而是把线上触发的原始事件下载下来在本地用同样的数据复现一遍。事件源不同函数的入参格式差异很大API网关、消息队列、定时器触发的事件结构各有各的格式。本地写一个测试脚本读取线上事件调用函数本地入口对比输出和线上日志基本能定位八成的逻辑问题。剩下两成是环境问题比如依赖缺失、环境变量不一致、网络不通这些靠本地模拟不出来但对结论有参考价值。第三板斧压测前三个必查项避开「测试全绿、上线全红」。第一查函数超时时间是否匹配压测请求的耗时分布第二查实例数上限是否和压测并发量匹配并发超过上限将直接失败第三查下游服务的连接池配置函数压测瞬间流量可能打满下游。这三项全过压测结果才有参考价值否则压测数据只能证明你的压测工具没问题。这套习惯帮我省下了大量排查时间。每接手一个新Serverless项目先把日志规范立起来再跑通本地模拟链路最后做压测前置检查项目的可维护性就有了保障。Serverless把服务器运维的负担卸给了平台但不意味着可以把工程素养一并卸掉。希望这篇实战笔记能帮你在Serverless部署上少踩几个坑。本文还有配套的精品资源点击获取