最近换工作,面试了几家公司,发现Serverless这个概念被问到的频率很高,几乎每家公司的技术面都会问到,有的问概念,有的问原理,有的问实际应用场景,有的问优缺点。Serverless是这两年很火的一个概念,是云计算的下一个阶段,很多公司都在尝试用Serverless架构,所以面试的时候经常会问到。

我之前对Serverless有一些了解,也做过一些小的实践,但是面试的时候,还是有一些问题答得不够好,回来之后又深入学习了一下。今天就来整理一下我面试中被问到的Serverless相关的问题,以及我的理解和回答,包括什么是Serverless、核心概念、工作原理、优缺点、适用场景、和传统架构的区别、常见的Serverless平台等,希望能给正在准备面试的朋友一些参考,也希望和大家一起交流学习。

一、什么是Serverless

第一个问题,也是最基础的问题,就是"什么是Serverless?",几乎每家公司都会问这个问题,考察你对Serverless的基本理解。

我的回答是:Serverless,翻译过来是"无服务器架构",但是这个名字容易让人误解,不是说真的没有服务器了,而是说,开发者不需要再关心服务器了,不需要自己管理服务器、操作系统、运行环境、扩容缩容这些事情,只需要写业务代码,部署到Serverless平台上,平台会自动帮你管理服务器、自动扩容缩容、自动运维,你只需要按实际使用的资源量付费,用了多少付多少,不用的时候不花钱。

简单来说,Serverless是一种云计算的架构模式,它把服务器的管理和运维工作,都交给了云平台,开发者只需要关注业务逻辑,不需要关心底层的基础设施,从而提高开发效率,降低运维成本,实现按需付费。

Serverless主要包含两个方面的内容:

  • BaaS(Backend as a Service,后端即服务):就是把后端的一些通用功能,做成服务,直接调用,不需要自己开发和运维,比如数据库服务、存储服务、消息队列服务、身份认证服务、推送服务等,这些都是BaaS,开发者直接调用API就行,不用自己搭服务器,不用自己运维。
  • FaaS(Function as a Service,函数即服务):就是把业务代码,写成一个个函数,部署到Serverless平台上,由事件触发执行,平台自动管理运行环境,自动扩容缩容,按实际执行时间和资源量付费。比如AWS Lambda、阿里云函数计算、腾讯云云函数,都是FaaS。

我们平时说的Serverless,更多的是指FaaS,也就是函数即服务,这是Serverless的核心。

面试官一般还会追问:"Serverless和传统的云服务器(比如ECS)有什么区别?"

我的回答是:主要有以下几点区别:

  • 管理粒度不同:传统的ECS,管理粒度是服务器,你需要管理整个服务器,包括操作系统、运行环境、应用部署、扩容缩容等;而Serverless,管理粒度是函数,你只需要管理你的函数代码,其他的都交给平台。
  • 付费方式不同:传统的ECS,是按服务器的规格和使用时长付费,不管你有没有实际使用,只要服务器开着,就要花钱,哪怕你的服务没有流量,也要付费;而Serverless,是按函数的实际执行次数、执行时间和资源量付费,用了多少付多少,没有请求的时候,函数不执行,就不花钱,非常节省成本。
  • 扩容方式不同:传统的ECS,扩容需要手动或者配置自动扩容策略,增加服务器,需要时间,有延迟,而且扩容粒度是整台服务器,不够灵活;而Serverless,是自动扩容,平台会根据请求量,自动增加函数实例,请求来了就执行,没有上限(当然有平台的配额限制),扩容粒度是函数实例,非常灵活,能应对突发流量。
  • 运维成本不同:传统的ECS,需要自己运维服务器,包括系统升级、安全补丁、监控告警、故障处理等,运维成本高;而Serverless,这些都交给平台了,开发者不需要运维,运维成本几乎为零。

二、Serverless的核心概念

第二个问题,是"Serverless有哪些核心概念?",考察你对Serverless的深入理解。

我的回答是,Serverless(FaaS)的核心概念主要有以下几个:

1. 函数(Function)

函数是Serverless的基本单位,就是你写的一段业务代码,部署到平台上,由事件触发执行。函数是无状态的,每次执行都是独立的,执行完就销毁,不保留状态,所以函数里不能存状态,状态要存在外部的存储里,比如数据库、缓存、对象存储等。

函数支持多种编程语言,比如Node.js、Python、Java、Go、PHP等,你可以用自己熟悉的语言写函数。

2. 事件(Event)

事件是触发函数执行的原因,Serverless是事件驱动的,函数不是一直运行的,而是有事件发生的时候,才会被触发执行。常见的事件源有:

  • HTTP请求:比如API网关收到HTTP请求,触发函数执行,这是最常见的,用来做Web应用、API接口。
  • 对象存储事件:比如上传文件到OSS,触发函数处理,比如图片压缩、视频转码、数据处理等。
  • 数据库事件:比如数据库里的数据发生变化(增删改),触发函数执行,做一些同步、通知、处理的工作。
  • 消息队列事件:比如消息队列收到消息,触发函数消费消息,做异步处理。
  • 定时事件:比如定时触发器,到了指定的时间,触发函数执行,做定时任务,比如每天凌晨统计数据、备份数据等。
  • 日志事件:比如日志服务收到日志,触发函数分析处理日志。

事件驱动是Serverless的核心特点,函数只在有事件的时候才执行,没有事件的时候不运行,不占用资源,不花钱,这也是Serverless能节省成本的原因。

3. 触发器(Trigger)

触发器是用来配置事件源和函数之间的关联的,你需要创建一个触发器,指定事件源的类型和配置,以及要触发的函数,这样当事件发生的时候,平台就会自动触发对应的函数执行。

比如,你要做一个API接口,就需要创建一个API网关触发器,配置HTTP方法和路径,关联到你的函数,这样当有HTTP请求到这个路径的时候,就会触发你的函数执行。

4. 实例(Instance)

实例是函数的运行环境,当有事件触发函数的时候,平台会启动一个函数实例来执行你的代码,执行完之后,实例不会马上销毁,会保留一段时间,等待下一个请求,如果一段时间内没有新的请求,实例才会被销毁,这就是"冷启动"和"热启动"的区别。

如果请求量很大,一个实例处理不过来,平台会自动启动更多的实例来处理请求,实现自动扩容;如果请求量减少,平台会自动销毁多余的实例,实现自动缩容。

实例的数量是动态变化的,根据请求量自动调整,开发者不需要关心,平台会自动管理。

5. 冷启动(Cold Start)

冷启动是Serverless里一个很重要的概念,也是Serverless的一个痛点。当函数很长时间没有请求,所有的实例都被销毁了,这时候来了一个新的请求,平台需要重新启动一个新的实例,加载运行环境,加载你的代码,然后才能执行函数,这个过程就叫冷启动。

冷启动需要时间,从几百毫秒到几秒不等,取决于运行环境、代码大小、依赖库等,冷启动会导致请求的响应时间变长,影响用户体验,特别是对延迟敏感的应用,冷启动是一个需要关注的问题。

如果函数有持续的请求,实例会一直保留,这时候来的请求,直接用已经存在的实例执行,不需要重新启动,这就是热启动,热启动很快,几乎没有延迟。

6. 运行时(Runtime)

运行时是函数执行的环境,比如Node.js 14、Python 3.8、Java 11、Go 1.16等,不同的语言有不同的运行时,你需要选择对应的运行时来部署你的函数。

运行时由平台管理,平台会负责运行时的升级、安全补丁等,开发者不需要关心,只需要写代码就行。

三、Serverless的工作原理

第三个问题,是"Serverless的工作原理是什么?一个请求从发起到函数执行,经历了哪些过程?",考察你对Serverless底层原理的理解。

我的回答是,以HTTP请求触发函数为例,一个请求从发起到函数执行返回,大致经历以下过程:

  1. 用户发起HTTP请求:用户通过浏览器或者客户端,发起一个HTTP请求,请求到API网关。
  2. API网关接收请求:API网关收到请求,根据配置的路由规则,找到对应的函数触发器,然后把请求转发给函数计算平台。
  3. 函数计算平台接收请求:函数计算平台收到请求,检查有没有可用的函数实例(热实例)。
  4. 如果有可用的热实例:直接把请求交给这个实例,实例加载函数代码,执行函数,处理请求,然后返回结果。这个过程很快,就是热启动。
  5. 如果没有可用的热实例:平台需要创建一个新的函数实例,分配资源,启动运行时环境,加载函数代码和依赖,然后再执行函数,处理请求,返回结果。这个过程就是冷启动,需要的时间比较长。
  6. 函数执行完成:函数执行完成,返回结果给API网关,API网关再把结果返回给用户。
  7. 实例保留:函数执行完成之后,实例不会马上销毁,会保留一段时间(比如几分钟到十几分钟,不同平台不一样),等待下一个请求,如果在保留时间内有新的请求,就直接用这个实例执行(热启动);如果超过保留时间没有新的请求,实例就会被销毁,释放资源。
  8. 自动扩容缩容:如果请求量很大,一个实例处理不过来,平台会自动创建更多的实例来并行处理请求,实现自动扩容;如果请求量减少,多余的实例会在保留时间结束后被销毁,实现自动缩容。

整个过程,开发者都不需要参与,平台会自动管理实例的创建、销毁、扩容、缩容,开发者只需要写好函数代码,配置好触发器,剩下的都交给平台。

四、Serverless的优缺点

第四个问题,是"Serverless有哪些优点和缺点?",这个问题也很常见,考察你对Serverless的全面认识,不能只说优点,也要知道缺点和局限性。

我的回答是:

优点:

  1. 无需运维,开发效率高:开发者不需要管理服务器、操作系统、运行环境,不需要做运维工作,只需要写业务代码,部署上去就行,大大减少了运维工作量,提高了开发效率,让开发者能更专注于业务逻辑。
  2. 自动扩容缩容,弹性好:平台会根据请求量自动扩容缩容,请求多了自动加实例,请求少了自动减实例,不需要手动配置,也不需要担心流量突增扛不住,能很好地应对突发流量,弹性非常好。
  3. 按需付费,成本低:按函数的实际执行次数、执行时间和资源量付费,用了多少付多少,没有请求的时候不花钱,对于流量不大、或者流量波动大的应用,成本比传统的一直开着服务器要低很多,非常节省成本。
  4. 高可用,稳定性好:平台本身是分布式的,多可用区部署,自动容错,函数实例出问题了,平台会自动启动新的实例,不需要开发者关心,可用性和稳定性都有保障,比自己搭服务器运维要可靠。
  5. 事件驱动,适合异步处理:Serverless是事件驱动的,支持很多种事件源,非常适合做异步处理、事件驱动的应用,比如图片处理、视频转码、数据同步、定时任务、消息消费等,用Serverless做这些,非常方便,成本也低。
  6. 多语言支持,灵活:支持多种编程语言,Node.js、Python、Java、Go、PHP等,开发者可以用自己熟悉的语言开发,也可以不同的函数用不同的语言,非常灵活。

缺点:

  1. 冷启动问题,延迟高:这是Serverless最大的痛点,函数长时间没有请求之后,再请求会有冷启动,延迟从几百毫秒到几秒不等,对于对延迟敏感的在线应用,用户体验会受影响。虽然可以通过预留实例、定时预热等方式缓解,但是会增加成本,也不能完全解决。
  2. 有执行时间限制:函数的执行时间是有限制的,比如AWS Lambda最长15分钟,阿里云函数计算最长2小时(不同平台、不同规格不一样),不能执行长时间的任务,比如大文件处理、长时间的计算任务,不适合用Serverless。
  3. 有资源限制:函数的内存、CPU、磁盘空间等都是有限制的,比如内存最大几个G,磁盘只有几百M,不能运行需要大资源的应用,比如大型的数据库、内存密集型的应用,不适合用Serverless。
  4. 调试和排错困难:因为函数运行在平台上,开发者不能直接登录到服务器上调试,只能看日志,调试和排错比较困难,特别是复杂的问题,排查起来比较麻烦。虽然平台提供了一些调试工具,但是还是不如本地调试方便。
  5. 厂商锁定问题:不同的云厂商,Serverless的API、触发器、运行时、配置都不一样,如果你用了某个厂商的Serverless,迁移到另一个厂商,需要改很多代码和配置,迁移成本比较高,存在厂商锁定的问题。虽然有一些开源的Serverless框架(比如Serverless Framework)能缓解,但是还是不能完全解决。
  6. 不适合长连接、有状态的应用:函数是无状态的,每次执行都是独立的,不适合做长连接的应用,比如WebSocket、实时通信、游戏服务器等,也不适合需要在内存中保存大量状态的应用。
  7. 监控和可观测性有限:虽然平台提供了基本的监控和日志,但是对于复杂的应用,特别是分布式的、多个函数调用的应用,监控和可观测性还是不够,排查性能问题、链路追踪比较困难。

五、Serverless的适用场景

第五个问题,是"Serverless适合用在哪些场景?不适合用在哪些场景?",考察你对Serverless应用场景的理解,知道什么时候该用,什么时候不该用。

我的回答是:

适合的场景:

  1. API接口和Web应用:对于流量不大、或者流量波动大的API接口和Web应用,用Serverless很合适,自动扩容,按需付费,成本低,开发快,比如小程序后端、活动页面、企业官网、管理后台等。
  2. 异步事件处理:比如图片上传后自动压缩、生成缩略图,视频上传后自动转码,文件上传后自动处理,数据同步,消息消费等,这些异步的、事件驱动的任务,非常适合用Serverless,成本低,不用一直开着服务器。
  3. 定时任务:比如每天凌晨统计数据、生成报表、备份数据、清理垃圾数据等定时任务,用Serverless的定时触发器很合适,到时间自动执行,执行完就释放资源,不用一直开着服务器,成本很低。
  4. IoT和物联网场景:比如物联网设备的数据上报、处理、告警,设备消息的处理等,IoT场景通常设备多,流量波动大,用Serverless自动扩容,按需付费,很合适。
  5. 小程序和移动端后端:小程序和移动端的后端,通常流量不大,但是功能多,迭代快,用Serverless开发快,不用运维,成本低,很适合,很多小程序的后端都是用Serverless做的。
  6. 数据处理和ETL:比如数据的抽取、转换、加载,日志的分析处理,数据的清洗、计算等,这些数据处理任务,通常是批量的、异步的,用Serverless很合适,按实际使用量付费,成本低。
  7. Webhook和第三方集成:比如接收第三方的Webhook回调,做一些处理,和第三方服务集成等,这些场景通常请求量不大,但是需要随时可用,用Serverless很合适,不用一直开着服务器。

不适合的场景:

  1. 长时间运行的任务:比如大文件处理、长时间的科学计算、视频渲染等,执行时间超过平台限制的,不适合用Serverless。
  2. 高并发、低延迟的核心应用:比如核心交易系统、实时竞价系统、游戏服务器等,对延迟要求很高,不能接受冷启动的,不适合用Serverless,或者需要用预留实例,成本会比较高。
  3. 长连接和实时通信应用:比如WebSocket服务、即时通讯、实时推送、在线游戏等,需要长连接的,不适合用Serverless,因为函数是短生命周期的,不能维持长连接。
  4. 有状态的、需要大量内存的应用:比如需要在内存中缓存大量数据的应用,大型的内存计算应用,不适合用Serverless,因为函数是无状态的,内存也有限制。
  5. 需要底层系统权限的应用:比如需要操作系统底层权限、需要安装特定系统软件、需要自定义内核的应用,不适合用Serverless,因为运行时是平台管理的,开发者没有底层权限。
  6. 流量非常大且稳定的应用:如果应用的流量非常大,而且很稳定,一直有很高的请求量,那么用Serverless的成本可能会比自己买服务器还高,因为按调用次数和执行时间付费,量大了之后成本会很高,这种场景用传统的服务器或者容器可能更划算。
  7. 对可观测性和调试要求很高的复杂应用:如果应用很复杂,需要很强的监控、链路追踪、调试能力,Serverless的可观测性有限,调试困难,可能不太适合,或者需要额外搭建可观测性系统,增加复杂度。

六、常见的Serverless平台

第六个问题,是"你知道哪些常见的Serverless平台?用过哪些?",考察你对Serverless生态的了解,以及实际使用经验。

我的回答是,常见的Serverless平台主要有:

国外的:

  • AWS Lambda:亚马逊的Serverless平台,是最早的、也是最成熟的FaaS平台,生态最完善,支持的事件源最多,功能最强大,很多Serverless的标准都是AWS引领的,国外用得最多。
  • Google Cloud Functions:谷歌的Serverless平台,和谷歌云的其他服务集成很好,支持Node.js、Python、Go等语言。
  • Microsoft Azure Functions:微软的Serverless平台,和Azure的其他服务集成很好,支持多种语言,和.NET集成特别好。
  • Cloudflare Workers:Cloudflare的Serverless平台,运行在Cloudflare的边缘节点上,延迟很低,适合做边缘计算、API代理等,和传统的FaaS不太一样,是边缘Serverless。

国内的:

  • 阿里云函数计算(FC):阿里云的Serverless平台,是国内比较早、比较成熟的FaaS平台,功能完善,和阿里云的其他服务(OSS、RDS、MNS、API网关等)集成很好,支持多种语言,国内用得比较多。我之前用过阿里云函数计算,做过一些图片处理和定时任务的小项目,体验还不错。
  • 腾讯云云函数(SCF):腾讯云的Serverless平台,和腾讯云的其他服务集成很好,支持多种语言,和微信生态集成很好,做小程序后端很方便。
  • 华为云函数工作流(FunctionGraph):华为云的Serverless平台,功能也在不断完善。
  • 百度云函数计算(CFC):百度云的Serverless平台。

开源的:

  • OpenFaaS:开源的Serverless框架,可以自己部署在Kubernetes上,支持多种语言,避免厂商锁定。
  • Kubeless:基于Kubernetes的开源Serverless框架。
  • Knative:谷歌、Pivotal等公司联合发起的开源Serverless平台,基于Kubernetes,现在比较火,是云原生的Serverless标准。
  • Serverless Framework:不是Serverless平台,而是一个开发框架,支持多个云厂商的Serverless平台,用统一的方式开发、部署、管理Serverless应用,能缓解厂商锁定的问题,很多人用这个框架开发Serverless应用。

我自己实际用过的是阿里云函数计算,做过一些小项目,比如图片上传后自动压缩生成缩略图、定时统计数据、小程序的后端接口等,整体体验还不错,开发很快,不用运维,成本也低,但是冷启动确实是个问题,特别是Java的函数,冷启动比较慢,Node.js和Python的冷启动会快一些。

七、Serverless的发展趋势和挑战

最后一个问题,有的面试官会问:"你觉得Serverless未来的发展趋势是什么?还有哪些挑战需要解决?",考察你对技术趋势的思考。

我的回答是:

发展趋势:

  1. 越来越普及,成为云计算的主流:Serverless是云计算的下一个阶段,随着云厂商的不断投入,功能越来越完善,生态越来越成熟,会有越来越多的公司和开发者采用Serverless架构,未来会成为云计算的主流模式之一,就像现在的云服务器一样普及。
  2. 冷启动问题不断优化:冷启动是Serverless最大的痛点,云厂商都在不断优化,比如通过预留实例、快照恢复、轻量级运行时、边缘计算等方式,降低冷启动延迟,未来冷启动的问题会越来越好,延迟会越来越低。
  3. 和容器、Kubernetes融合:Serverless和容器不是对立的,而是融合的,现在很多Serverless平台底层就是用容器实现的,Knative这样的基于Kubernetes的Serverless平台也越来越火,未来Serverless和容器、Kubernetes会深度融合,开发者可以根据需要选择,也可以混合使用。
  4. 边缘Serverless兴起:随着5G和物联网的发展,边缘计算越来越重要,Cloudflare Workers这样的边缘Serverless平台会越来越多,把函数部署到离用户更近的边缘节点,降低延迟,更好地支持IoT、实时应用等场景。
  5. 可观测性和工具链不断完善:现在Serverless的调试、监控、链路追踪还不够完善,未来会有越来越多的工具和平台,完善Serverless的可观测性和开发工具链,让开发、调试、部署、监控Serverless应用更方便。
  6. 标准化,缓解厂商锁定:现在不同厂商的Serverless平台API不一样,存在厂商锁定的问题,未来会有更多的标准化工作,比如Knative、Serverless Framework等,推动Serverless的标准化,让应用能更方便地在不同平台之间迁移,缓解厂商锁定。

挑战:

  1. 冷启动和延迟:虽然在不断优化,但是冷启动还是Serverless的一个挑战,特别是对延迟敏感的应用,如何进一步降低冷启动延迟,是需要持续解决的问题。
  2. 可观测性和调试:Serverless的分布式、事件驱动的特点,让监控、调试、链路追踪比较困难,如何提供更好的可观测性和调试工具,是一个挑战。
  3. 厂商锁定和标准化:不同厂商的平台不兼容,迁移成本高,如何推动标准化,缓解厂商锁定,让开发者有更多选择,是一个挑战。
  4. 安全和隔离:函数是多租户的,多个用户的函数运行在同一个平台上,如何做好安全隔离,防止恶意函数影响其他函数,防止数据泄露,是一个挑战。
  5. 成本和性能的平衡:Serverless按需付费,流量小的时候成本低,但是流量大的时候成本可能会很高,如何在成本和性能之间找到平衡,让用户用更低的成本获得更好的性能,是一个挑战。
  6. 有状态和长连接场景的支持:现在的Serverless主要适合无状态、短生命周期的函数,如何更好地支持有状态的应用、长连接的应用,拓展Serverless的适用场景,是一个挑战。

八、写在最后

Serverless概念面试题:我被问到的那些问题。

以上就是我面试中被问到的Serverless相关的问题,以及我的理解和回答,整理出来分享给大家,希望能给正在准备面试的朋友一些参考,也希望和大家一起交流学习。

Serverless是这两年很火的技术,是云计算的下一个阶段,它改变了我们开发和部署应用的方式,让开发者不需要再关心服务器,只需要专注于业务逻辑,大大提高了开发效率,降低了运维成本,实现了按需付费,是一种很有前景的架构模式。

当然,Serverless也不是银弹,不是所有的应用都适合用Serverless,它有自己的优点和缺点,有自己的适用场景和不适用场景,我们在做技术选型的时候,要根据实际的业务需求,综合考虑,选择最合适的架构,而不是盲目跟风,为了用Serverless而用Serverless。

我自己对Serverless也是在学习和实践中,这篇文章里的理解和回答,可能有不对的地方,欢迎大家指正,也欢迎大家交流自己对Serverless的理解和使用经验,一起学习,一起进步。

最后,用一句话结尾:"Serverless不是没有服务器,而是让开发者不再关心服务器;技术的发展,就是不断把底层的复杂性封装起来,让开发者更专注于业务价值。"愿我们都能跟上技术发展的趋势,学好新技术,用好新技术,做出更好的产品。