腾小云导读:
通过本文你可以了解到:第一,Serverless架构介绍;第二,对云函数产品介绍;第三,Serverless使用场景。
本文是黄文俊在云 社区沙龙《Serverless架构开发与无服务器云函数(Serverless Cloud Function,SCF)部署实践》上的分享。
本文共:7463 字,预计阅读时间:19 分钟
讲师介绍:黄文俊,曾负责企业级存储、企业级容器平台等产品的架构与开发,目前主要负责SCF腾讯无服务器云函数产品相关。对容器平台、微服务架构、无服务器架构以及DevOps等多种热门技术领域均有涉猎。
以下是分享全文:
大家好,自我介绍一下,目前我是腾讯云无服务器云函数产品负责人。我做了很多年后端开发。今天是从一个程序员角度讲解一下我们怎么样用Serverless架构。
我将本次讲解分为几块:第一,Serverless架构介绍;第二,对云函数产品介绍;第三,Serverless使用场景。
讲Serverless架构之前我们可以来看一下整个云的发展过程,在没有云之前大家可能都是用的物理服务器,早期时候大家都用的物理机托管方式,采购一些服务器在机房里托管,这个时候大家前期要选择物理机型号,要做好IDC网络;如果出了问题还要请IDC人员帮你操作。这些设备的投入和运维成本还是很高的。
云时代到来之后,由于虚拟化技术的运用,我们用上了云主机。云主机是大家直接在云上做虚拟机购买,开通就可以使用。这时候我们称之为IaaS(基础设施即服务),这种情况下就无需物理机运营,直接放到云平台来做。而之后随着容器技术的发展,我们有了容器平台,或者叫PaaS(平台即服务)。在容器平台到来之后实际上还存在一部分基础设施运维问题,但是这时候基础设施逐渐下沉到运维人员进行操作;而从应用开发者角度来看,他们已经不用再去关心虚拟机,或者操作系统。在这种情况下,应用开发人员更多的去关注应用所需要的计算资源或者存储资源的使用。继续向前发展,我们到了FaaS(函数即服务)。这时候运维人员不需要关注底层的运维,而是按需运行的能力。业务开发人员能够进一步做与业务相关的事情。
接下来我们来看一下Serverless架构是什么。
Serverless从物理机或虚拟机的使用上进行了分离,更关注上层业务的运行情况。Serverless架构包含两块:函数即服务和后端即服务。函数即服务提供的是计算能力。原有的计算能力,无论是容器也好,虚拟机也好都承载在一定的操作系统之上,函数即服务把计算能力进行了进一步抽象,我们在后文再继续进行展开。另外,Serverless还有后端即服务,比如对象存储,数据库应用,缓存服务,我们也可以称之为Serverless,因为这些服务也能够在云上提供开通即服务,开通即使用的能力。在使用这些产品时同样不需要关注它的服务器是什么样的,它的服务器部署在哪里,而是服务开通就可以使用了,后面的运维工作都交给了云,所以不用感知它的最底层服务器,因此我们也可以把它称之为Serverless。这种服务就称之为Serverless后端即服务。这两个合起来可以称为Serverless架构。
函数即服务的工作原理是什么样的?
在Serverless上是怎样提供计算能力的?大家原来使用容器或者虚拟机的时候都可以知道,我们把代码上传到容器或者上传到虚拟机,然后启动一个进程,代码就可以运行,它就可以接受外部的请求,做一些实时的响应。Serverless和原有的容器或虚拟机不同,实现的是计算托管服务,Serverless用户首先要做的,是把我们称为云函数的代码,提交到平台上进行代码托管;然后要做的是配置触发器。为什么需要配置触发器?因为云函数的运行方式是触发式运行,有触发的时候,代码才会真正运行起来。所以配置触发器意味着我们给它设置了一个触发源,也就是定义了在什么事件下代码才真正运行起来。用户代码托管到平台之后,事件没有到来之前,它仅仅是代码文件和配置存储,代码并没有运行。什么情况下运行?是当事件触发真正到来的时候,云函数才会真正启动一个实例,这个实例就意味着一个计算单元。计算单元被拉起后,这个事件就被传到这个计算单元中进行计算处理。如果这个触发源的事件很多,并发很高的情况下,平台会根据事件的堆积情况,或者事件到达的速度,自动把同一份代码和配置拉起多个实例进行并发处理。因此可以看到Serverless的运行是按需运行,意味着只有在事件到来的情况下,代码才会被拉起,才会运行起来。
自动并发,是指云函数平台会根据事件堆积情况自动的进行并发,自动拉起多个实例进行处理。而原有的容器或者虚拟机如果要进行并发的话还是要有一定的手工参与,比如启动更多的容器,或者加入更多的虚拟机来承载高并发的请求。而函数即服务是完全自动的运行。
按需运行带来的另外一个特点,是代码在运行起来之后上才会占用计算资源。函数即服务的费用也是根据按需运行来的,也就是函数运行的时候才进行计费;而没有使用的情况下不会计费。实际上大多数互联网业务只有白天的时候,甚至六点之后大家下班之后业务才会迎来高峰,而到凌晨之后实际上没有多少请求的,因此函数即服务能够很好的满足波峰波谷来削峰填谷的能力。
从上面的原理可以看出函数即服务的一些特点,比如说代码托管,云函数平台所提供的直接就是运行环境,也就是支持各种开发语言的环境;对于开发者或者函数服务使用者来说,并没有感知到它下面的服务器在哪里,而是由函数平台完成了函数运行的调度。因此实际来讲不需要运维,包括操作系统优化,服务器维护等等这些都是由平台进行承载。
而秒级部署意味着函数在真正的被请求的时候才运行。而这个请求才运行代表着当请求到达平台的时候函数才会被实时拉起并运行。运行完成后如果没有后续请求,实例也会退还。
由于函数运行是事件触发的,而事件其实包含很多种类,有各种触发器都可以对接云函数。有越多的触发器对接,云函数所能提供的场景也就越多。
对于开发者来说,使用云函数的情况下,他真正关注的是应该业务,是使用代码去聚焦他的业务逻辑,例如是拿到这个事件后该进行什么样的逻辑操作,进行什么样的业务存储,而不需要去关注怎么使用业务代码实现高并发,怎么样实现高请求的承载能力。因此这里看到函数即服务能够为应用开发者带来一些便利,而自动并发本身也是函数即服务所具有的特点。
而对于腾讯云无服务器云函数,在最开始开发产品的时候,我们目标也是一样,就是把计算进行托管。在计算托管的情况下,我们使用计算就像我们使用腾讯云对象存储一样,在使用的时候不用关心最底层的运维,不用关心虚拟机或者物理机是否安全。和对象存储进行对比也能看到,我们计算也是按照实际使用情况进行计费。当然现在云函数还处于免费期,大家可以随时使用。
从使用方法来说,云函数本身,或者说函数即服务这种产品本身的使用方法都是很简单的。我们在开发的时候更多的关注于核心代码的编写。核心代码的意思实际上就是真正的业务逻辑。而且业务逻辑里不需要考虑高并发,因为由刚才给出来的函数即服务这种计算特点来看的话,在高并发请求的时候是通过多个实例处理进行,因此业务代码在编写的时候,就关注单个事件的处理就行。因此,第一步的核心的就是编写核心业务代码,就是用代码要实现什么样的业务。后续就是配置触发方式。配置触发方式就是把函数代码和触发源对接起来。和云平台上其他的产品进行对接,需要什么样的事件,处理什么样的事件,进行什么样的逻辑处理,做好这样的触发源对接后,函数就能够在事件产生的情况下运行。
因此,从整个使用方法来看的话,大家真正要做的是两步:第一,编写代码,第二,配置好触发。而对于底层的基础设施,环境配置这块都不需要大家操心的。
目前,腾讯云函数从运行环境来说目前已经支持了Python、Nodejs、PHP、Golang、Java等语言的开发运行环境。
接下来是触发器,因为触发器越多,云函数所能去使用的场景其实也越多,我们已经实现的触发器有定时触发器;腾讯云对象存储服务,包括文件的上传、删除等时间;CMQ 消息队列服务;API 网关服务,这个是通过serverless 架构实现 API 服务的一款重要触发器;另外,还有ckafka,这个是腾讯云提供的kafka能力。目前kafka算是一个开源产品,我们腾讯云把它包装后放到云上来,也是兼容标准的kafka协议。因此在很多情况下直接迁移到腾讯云不需要任何修改。因为kafka本身作为消息传递的载体,跟腾讯原有的消息队列类似,由消息来执行云函数。
下面介绍一下在什么场景下Serverless可以落地?
第一,在Serverless场景中最常用到的就是API服务。大家知道实现一个API服务,无论是把API给到浏览器应用,还是给到手机APP使用,还是给到小程序应用,给到它们的时候是以API实现的。要实现这个要有WEB服务器接收连接,对接后端的业务代码,如果你要再进行文件存储,后端的结构化存储,或者有一些缓存需要读写,你的应用服务器后面可能还要对接相应的文件存储,结构化数据库,后续如果想使用缓存,再对接到相应的服务器或相应产品。如果把现有的API服务向Serverless架构演进,那么它将怎么样呈现呢?
在不改变 API 的情况下,它的前端浏览器应用、APP、小程序,都可以无缝对接上来。而使用API网关来承接 API 请求,当这个请求来到API网关,由它转发给云函数,触发云函数执行。云函数执行时运行业务逻辑。实际上云函数运行时要求无状态,因此这样的状态存储也需要用到后面的一些存储,无论做缓存也好还是数据库也好都要用上。因此,云上提供的产品一样可以进行对接。像文件存储的话可以用对象存储来进行。数据库的话一样的有相应的数据库产品,结构化还是非结构化数据库都有相应的产品可以使用。同样的,缓存也有相应的产品做对接。云函数通过代码编写,直接进行数据库的读写,或者缓存的读写都是可以的。
从整个服务架构来看的话,我们使用最前面的API网关,提供是API能力,甚至进一步能够直提供有SDK服务,更加的方便开发。SDK提供了各种开发语言来直接进行API调用。云函数在中间起到的是业务逻辑处理的作用,而状态数据或者其他业务数据的存储是依赖于后面的文件存储或者数据库进行的。API服务也是Serverless最常用的一种落地形式。
这里介绍的场景,都是我们客户在实际使用的场景。在 serverless落地场景中,对对象文件的处理也很常见。对象文件处理指的是对对象文件进行操作后的回调处理。回调通常是在对象文件创建或删除操作后产生的事件。云函数可以在获取到这个事件后进行后续的处理。这里常见的处理逻辑是下面几种,比如说图片处理,针对图片去生成各种尺寸的缩略图或者进行裁剪,然后再次存储到对象存储数据中,之后可以根据不同客户端的请求展示不同大小的图片到前端。
文件批量打包,用户需要进行文件筛选和打包的时候可以通过使用云函数来处理。在上传文件后,如果需要选择哪些文件来打包,把文件生成压缩包以供下载,这都可以由事件处理来进行。
日志归档分析,以及业务系统回调,也是云函数所承载的业务逻辑。比如说日志归档分析这种用法,用户会把每天的前端应用服务器的日志上传到对象存储中归档,归档后会触发云函数执行,云函数会拉下这些日志文件进行实时分析,它会抽取这些日志中的错误数,或者是其他业务相关或者用户关注的内容,然后再把它抽取到的信息或者统计到的信息写回数据库,供用户后续进行排查、使用。用户自身API调用也是,例如用户生成的一些视频文件上传到对象存储,会触发云函数,将上传文件的信息通知到用户的转码系统,通过视频转码转成不同分辨率然后再进行存储。当然转码是用户自身实现的业务系统,这块通过回调通知,通知它自身的业务系统。这些就是云函数在Serverless架构和对象存储连用的落地场景。
再就是CKafka消息处理。CKafka目前比较多的应用场景是做日志存储和日志搜集,例如有多台应用服务器在不断产生日志的情况下,可以把日志写到CKafka,然后CKafka再进行归档和后续分析。而 CKafka和云函数对接是由CKafka收到的信息来进行触发的。日志搜集后,要归档的日志,一般存储到对象存储当中。这种情况CKafka消息,会被推送给云函数,云函数再再把这些消息写到对象存储中去。有些用户不是写对象存储,而是写数据库,以数据库形式归档,其实也是一样的。有的使用场景,需要进行消息分析,会实时拿到消息后立刻分析里面的关键字,如果捕捉到了关键字,会立刻把这些消息推送到ckafka 的另一个topic 中,去及时的发出告警给到业务和运维人员。这也是 serverless 的一种用法,就是对消息的分析和转发。
消息队列和CKafka类似,但是消息队列一般不是进行日志的搜集,而是进行业务解耦。消息队列 CMQ 是腾讯云提供的一个高可靠金融级消息队列,通常进行一些业务级消息转发和处理。使用这个产品,实际上做的是业务解耦。云函数在这里承载着消息的逻辑处理过程,它能够在接收到消息后对消息立刻进行业务处理。这个业务处理就是实际的业务逻辑,比如我要根据里面某个消息进行判断,判断它是否合适,要不要进行后续的转发,或者转发到另外的业务系统中去?这就是业务之间执行的逻辑。
同时,我们也可以使用云函数,再次进行消息的分派,做状态转移。这个状态转移和后面消息转发都是一样的,它会识别消息里的内容,根据消息里的内容进行转发。这种情况下类似于我们使用云函数进行逻辑处理,把它转移到合适的消息队列,然后再进行处理。这也是我们所见过直接用云函数进行消息派发的使用方式。
最后一种形式现在也不少,就是利用定时器触发。原本大家更多是在运维场景下使用定时任务,在原有使用 crontab 脚本的情况下,大家通常还要关心脚本运行是否成功,这台虚拟机是否还在工作。云函数抛弃了大家使用传统的虚拟机或者物理机来去写crontab脚本还要确保可靠性的问题。而在实际使用定时器触发的场景下,这里也有几种用法:一种是业务拨测。这个是周期性的去拨测业务是否还在工作,如果出现异常的情况下能够及时的发出告警,发出邮件或者短信告诉到运维或开发人员。
另一个是定时备份,这个是在所需要的周期内,比如每天,或者每两天对数据库进行备份,针对数据库需要做数据导出,导出后再将导出内容以文件的形式存储到合适的地方,例如对象存储中,做好定时备份。
还有一个是定时数据计算。因为有些计算是根据一段时间内的统计之后,进行计算并展示。在实际场景中,我们腾讯云内部有业务就是在进行定时数据计算,每两小时做一次统计,然后再把统计数据写到数据库做后续业务的展示以及业务分析。
总结:Serverless架构本身给用户带来什么?
它实际上就是允许我们更关注业务代码,因此可以更快速的构建业务然后上线。现在互联网开发速度越来越快,因此大家期望的是进一步加快开发和业务真正上线的速度,提高迭代的能力。因此,使用Serverless的话可以更快速让业务上线,让我们更快实现我们的想法。而按需使用是我们这个业务在上线之后,在真正产生请求后,业务才会被调动触发,才会有计算。而如果你的业务产生了爆发式增长,其实也不需要担心平台承载能力或者业务扩展是否跟得上,因为平台提供自动扩展能力,降低了大家对运维的诉求,大家不用关心很底层的东西,而运维人员也可以更偏重流程化和业务相关的运维。这就是Serverless架构给大家带来的一些好处。而作为Serverless里的核心,函数即服务这种产品,是Serverless中所呈现出来的计算型的组件,大家也可以看到它和触发源和后端的各种产品或服务有紧密关联,它可以更多的被看做是云时代的脚本,类似于黏合剂,把前面的触发源和后端的各种存储,数据,服务进行了黏合,真正实现架构落地,才是真正实现业务逻辑落地的能力。
Q&A
Q:云函数有无限扩展能力,但是整个系统也有可能是有限制的,比如它的背后的数据库和存储,我能不能设这样的一个扩展上限?
A:这可以设置上限的。目前可以通过提交工单的方式来设置期望的合适上限。扩展可以在后台设置一个合适值,并发实例扩展到这个就不会再扩展了,避免大量实例连接造成后端的数据库或存储超过连接数限制。
Q:实现 API 服务有哪些开发方式?
A:云函数实现 API 服务的开发方式有好几种,一个是全部在一个函数里完成,路径和方法解析都在函数里进行。这也是偏传统的开发方式。另外一种是进行拆解,每个函数处理一个 API 路径和方法的请求,这种是微服务的开发方式。
而函数和函数之间调用也是可以实现。一种是直接使用云API,一种是使用 API网关包装后的 API。云函数被触发调用的话,除了介绍的很多触发器,在不使用这些触发器的情况下,通过代码或者脚本也可以通过腾讯云的云API调用。
Q:在事件触发的时候,就是CMQ事件触发的时候,是否可以保证函数被执行呢?因为不像API网关,调用一下函数可以启动,前端可以感知到。但是CMQ,就是扔到消息队列能否保证这个函数被执行呢?
A:因为不像API网关是同步调用。同步调用就是这个调用在运行过程中如果出了问题,无论是平台,比如说资源不足,并发不够,或者比如使用的超时了,这个时候可以立刻感知到。而像CMQ或者CKafka都是异步的,这样意味着调用后你感知不到,这个消息什么时候执行,执行结果都没法感知。这种解决方法有两种:一种是函数运行后的结果输出,把消息处理后的输出结果再放到另一个消息队列中去,让你外部的业务系统能够感知到。当然这种对外通知也是异步通知。同步通知是另外一种,就是函数里可以对自身业务进行回调API,可以通过代码知道现在的数据处理是什么样的结果,处理完后可以立刻回调到API让业务系统接收到处理结果。
Q:像COS触发,拿视频转码来说,这个有可能在300秒内处理不完。现在函数设置时间只能最高300秒,这个有什么解决方案吗?
A:为什么各家的云平台,都把这个时间大致定在这个范围内,就是不希望在云函数中进行太重的计算。视频转码就属于太重的计算,而云函数提供的包括CPU能力,内存大小都有限,实际上都不太适合在云函数内进行转码。实际上可以用一些视频服务来实现转码,使用云函数来做这两者之间的桥梁,例如对象存储的事件触发后,云函数拿到这个事件通过调用视频转码服务来转码,而不是在云函数转码。目前腾讯云有这个服务,你可以试试看。