SCF(Serverless Cloud Function) 无服务器云函数是腾讯云无服务器 (serverless) 执行环境,帮助用户在没有购买和管理服务器时仍能运行代码。用户只需要使用云平台支持的语言编写核心代码及设置代码运行条件,代码即可在腾讯云基础设施上弹性、安全地运行,无须关注底层计算资源,包括服务器 CPU、内存、网络、代码部署、弹性伸缩、负载均衡等服务。
使用无服务器云函数将可免除所有运维性操作,企业和开发者可以更加专注于核心业务的开发,实现快速上线和迭代,把握业务发展的节奏。
随着云计算市场的成熟,用户对云计算接受程度逐渐提高,借助各类基础云组件,已经可以将业务上线时间从月级缩短到天级,但对比传统模式,用户仍需基于云组件重构非功能性需求。
而云函数则尝试将业务算法和流程提炼出来交由用户实现,打通各种云服务,并实现通用的负载均衡、自动伸缩、故障容灾、安全监管等通用功能,真正使得用户像搭积木一样打造个性化服务,将业务上线时间从天级缩短到分钟级。
相比云主机,云函数更适合于支持微服务架构业务场景。以图片多规格压缩服务为例,该服务在用户上传图片至 COS 时,自动将原始图片压缩成适配手机、平板、电脑等多种大小的规格。
如利用云函数实现该服务,用户只需创建函数,定义函数触发条件为“图片上传”,在线编辑或使用 IDE 完成代码编写后上传,服务即构建完成。用户上传图片时,自动调用定义的函数完成图片的多规格压缩,云函数平台根据上传并发量自动扩缩容函数实例,并最终按照实际调用消耗计费。
从该示例可以看出,云函数为用户带来的主要价值为:
加快用户服务上线时间,用户只需实现业务算法及流程,上线时间缩短为分钟级 ;
减少用户的运营负担,用户无须承担服务扩容,故障恢复运维工作 ;
消除用户的资源成本,用户无需承担资源闲置费用,只为实际调用消耗付。
云函数平台整体架构原理如图所示。
云函数为用户提供 SDK/WEB UI 两种使用方式,并通过事件注册与回调机制与其它云组件打通,提供标准的 API 接口;调用分发根据函数所属的区域,用户,名字,版本号,鉴权等信息申请函数实例,并将调用均匀的分发到可用函数实例;
函数管理负责创建 / 修改 / 删除函数,并提供函数代码管理,版本管理等功能;函数调度根据函数资源需求选择合适的位置创建 / 销毁函数实例;函数实例部署用户定义的函数,负责函数的执行及监管。
从云函数的定位及架构原理看,衡量云函数平台的关键技术指标可概括为:
不仅支持业务快速上线,且能实现持续发展;
不仅支持业务按需取用,且能释放闲置资源;
不仅支持业务永不中断,且能扩展运行范围;
不仅支持业务自由运行,且能避免干扰入侵;
下文将展开详述。
支持业务分钟级上线,需要尽可能的减少用户研发工作量,云函数用户仅需提供简单的函数配置及代码即可完成上线。以图片压缩为例,用户自行编辑 python 代码如下,即可实现一个图片压缩服务:
其中第 1 行引入依赖库,第 4~9 行解析输入参数,第 11 行调用库完成图片压缩,12~15 行判断结果及返回。用户可在线完成代码的编辑并提交,也可像开发本地程序一样使用喜欢的 IDE 编辑,调试通过后打成 zip 包通过 SDK 提交,提交成功服务即上线。
支持业务可持续发展,需提供用户函数平滑升级及版本变更能力,当用户更新函数代码或配置后,新调用请求被分发至新函数实例,原调用请求执行完成后,旧函数实例自动消亡,服务在客户不感知情况下平滑更新。
即将支持用户函数多版本管理,将函数别名映射至用户指定版本,在客户不感知情况下实现多版本间平滑切换。
函数运行过程中间,用户打印日志,标准输出 / 错误输出日志分类上传至腾讯云日志服务平台,用户可实时监控函数运行情况。
要支持云函数真正按需取用,需实现用户第一次调用时延迟分配资源,函数调用过程如下图所示:
云函数平台在调用分发时,会判断是否有函数实例存在,如若不存在,则实时启动实例,实例启动完成后,才开始执行函数调用。为了达到第一次调用足够快的目标,在调用过程中需分阶段逐层优化:
分发调用阶段:需减少调用分发层级,比如对于用户主动发起的 http 同步调用,正常路径可免去存入持久化队列过程;
镜像及代码下载阶段:需尽量预部署以减少下载时间,比如对新提交函数,并行启动预加载,使得第一次调用发起时无须再去实时下载;
容器启动过程:需简化容器启动脚本,使得启动过程尽量轻量,对于对延时敏感的业务,提供实例预留机制,用户可选择预留少量实例以减少第一次调用的额外延时;
执行函数调用:需尽量减少函数参数,返回数据及日志传递导致的内存拷贝次数;
返回调用:需尽量减少返回层级;
通过逐层优化,第一次调用平台耗时可控制在 2s 左右,后续调用平台耗时控制在 5ms 左右。随着客户请求量的增加或减少,函数实例随着自动扩缩容,一般算法如下:
If 当前排队请求数 / 当前实例数 > 扩容阈值:扩容实例;
else 当前排队请求数 / 当前实例数 < 缩容阈值:缩容实例;
当缩容至最后一个函数实例时,为避免函数实例短时间内重复启动 / 停止导致客户调用延时增加,需保留一段时间延迟释放。
要支持云函数永不中断,需实现 2 个容灾目标:硬件故障时服务不中断、平台升级时服务不中断。
为实现这 2 个容灾目标,整体架构需实现 set 化,且在各层均需对应的支持:
接入层:基于腾讯云 CLB 实现横向扩展,负载均衡,7 层路由能力;
逻辑层:实现模块无状态化,模块内部无状态数据,可随意启停替换;
数据层:采用一致性存储仓库存储关键数据;
节点层:实现快速节点故障检测及替换恢复;
比如平台内部 Invoker 模块实现硬件故障时,如下图所示,由于 invoker 模块无状态,故障时可由接入层 CLB 模块自动剔除,剔除后新请求分发至剩余 invoker 模块实例,已接收的异步事件可由其它 invoker 重试完成,同步 http 调用会直接返回给用户错误请求,由用户重试,在故障 invoker 实例恢复后,自动添加至 CLB 中,继续分担负载。
当平台需要升级 API 接口时,采用只增不改策略,提供新版本 API 接口,保持用户原有服务兼容性,用户采用新接口时,CLB 通过 7 层路由,路由至新版本 invoker 模块实例,旧版本实例随着负载的降低逐步缩容,新版本实例随着负载升高逐步扩容,以此实现了用户透明的版本平滑升级。
要实现云函数需与各类云组件打通,需要云组件提供事件注册及回调机制,云组件提供可注册事件及对应的回调接口,云函数确保云组件通信的用户权限打通传递。当前云函数实现了与腾讯云 COS 存储组件的打通,马上将实现与腾讯云 CMQ、云监控等其它云产品的打通,并将运行范围扩展至 CDN 节点及 IOT 设备网关,实现边缘计算。
云函数需支持用户本地测试通过的代码无缝在云函数平台运行,需具备足够的兼容性,及用户函数运行时环境,需要具备和用户开发测试环境类似的软件包,安全等配置 ; 同时避免函数间干扰,防止恶意入侵。
为了避免用户函数间干扰,云函数使用了 Docker 容器来封装函数实例,通过 docker 的名字隔离、空间隔离、权限限制等机制实现用户间隔离,辅以实时冲突监控调度等措施及时处理 CPU cache 层面的性能干扰。
为了避免用户执行代码影响整个云函数平台,如下图所示,实现了云函数管理平台与用户函数的隔离,用户函数无法感知管理平台的网络地址,运行日志等信息,从而无从影响云函数平台的运行。
为了避免用户恶意代码对网络的探测和入侵,如下图所示,用户函数实例被限制到了受限的公共 VPC 网络,需通过网关实现与外网服务、其它函数实例、云组件的互访,同时,为了支持用户函数实例与个人 CVM 虚拟机的集成,云函数平台通过弹性网卡打通了与其私有 VPC 的网络通信。
近年 Serverless、微服务等理念逐步深入人心,云函数开始被用户了解接受。为了满足用户对于更快速上线、更低成本、更优架构的求索,腾讯云推出了云函数产品。
用户不妨从解决实际问题开始试用云函数,比如实现一个简单的服务拨测工具,实现一个定时任务,实现存储于 COS 的图片、视频、文件的计算等。
随着云函数可联动云组件的拓展,支持语言的丰富,调试工具,流程引擎等逐步完善,云函数会逐步成为整个云平台的粘合剂,将各种云组件融合一起,让云成为你的公共后台,到时可支持更为复杂的状态服务场景,成为用户通用体贴厚实的后盾。
Q: 请问代码怎么部署到 docker 中?
A:直接将代码下载至母机,再将代码目录挂载至 Docker
Q: 云函数是通用的 还是只能在云平台运行?
A:云提供了云函数服务,自己也可搭建,目前 github 上有不少开源云函数平台,比如 openlambda,iron.io 等,建议直接使用云的服务,因为可以和多个云产品打通,单靠云函数自身难以构建完整服务。
Q: 事件传递使用的是队列吗?
A:异步事件用了 CMQ 消息队列持久化存储,同步事件未使用
Q: 请问云函数对开发语言有限制否?如果有,目前对 Go 语言的支持如何?
A: 目前支持 python 2.7/3.6, node.js 4.3/6.10, Java8,如果有通用的用户需求,可以支持其它语言,比如 php,go 等
Q: 有系统函数调用吗?自定义函数的颗粒度有何建议?
A: 绝大部分的系统调用都可调用,除了一些危险操作,比如关机,重启,网络服务监听等,函数颗粒度可参考微服务的设计原则,将功能尽量拆细
Q:可落地吗?
A:已有不少用户案例,后续会做些分享,不妨亲自试试,当前是免费的,会一直提供免费包,有需求直接给我们提
Q: 云函数支持 kotlin 语言吗?
A: 之前没用户反馈需要这种语言的支持,不过我个人挺看好,会持续保持关注
Q: 请问将请求调度函数实例,这个调度算法的实现?
A:其实这里就是通用的负载均衡和扩缩容算法,这里比较复杂的是提前预测需要扩容,后续会详细分享。
Q: 能介绍下 将请求调度到函数实例的实现吗?
A:这里有个 invoker 模块对每个函数维持有一个请求队列,目前没设置优先级,按照先来先到的顺序依次调度,调度时会从函数所有可用的函数实例中,选择一个下发。函数实例里有个循环接受请求,收到时传递参数调用用户函数。
Q: 代码可以下云落地吗?
A:代码里一般会涉及其它云产品的调用,所以一般对云平台有一些依赖,可以关注下开源的 serverless 框架,在公有云云函数上封装了一层,用来解除依赖,实现在各个云平台的平滑迁移。
Q: 云函数的代码有哪些限制?比如什么样的函数不可以调用,什么样的库不能 import?
A:可以基本认为无限制,但会禁止恶意行为,比如关机,重启,端口扫描等;也会禁止端口监听,因为常驻进程不符合云函数按需启用的原则。如果预装库不符合要求,可以自行将依赖库打包至 zip 里上传。
Q: 下层的容器编排是基于什么做的?k8s 么?
A:基于腾讯云的容器平台,其底层是 K8S。
细说云计算
「细说云计算」是InfoQ旗下关注云计算技术的垂直社群,投稿请发邮件到editors@cn.infoq.com,注明“细说云计算投稿”即可。