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