作者 | 宋文龙(闻可)  阿里云全球技术服务部高级交付专家

什么是无服务计算

无服务器计算(Serverless Computing)在构建和运行应用时无需管理服务器等基础设施。它描述了一个细粒度的部署模型,在该模型中,应用被拆解为一个或多个细颗粒度的函数,在云端托管环境中被触发运行,然后根据需要执行、扩展容量并且计费。各大云厂商 Amazon、微软、Google、IBM、阿里云、腾讯云、华为云相继推出 Serverless 产品。

无服务计算本身是一个概念或者理论模型,落地到具体技术上主要有函数即服务(FaaS)以及后端即服务(BaaS)两种形式,阿里云提供函数即服务 FaaS 产品。

阿里云对于 FaaS 的定义如下:

函数计算是事件驱动的全托管计算服务。使用函数计算,您无需采购与管理服务器等基础设施,只需编写并上传代码。函数计算为您准备好计算资源,弹性地、可靠地运行任务,并提供日志查询、性能监控和报警等功能。

关于 FaaS 的详细介绍官方文档已经讲的很清楚,本文不再赘述。本文重点讨论无服务计算的应用场景以及应用实践。

无服务计算应用场景

1. 无服务计算的优势

无服务计算有很多优点,个人认为其中最主要的有三点:

  • 使用无服务计算,用户无需考虑基础设施,可以更加专注于业务逻辑;
  • 无服务计算支持弹性伸缩,按需使用,按量计费,非常适合流量不稳定、有明显波峰波谷的业务;
  • 无服务计算是云原生产品,可以无缝对接各种云上产品,作为黏合剂串联各种云原生产品。

下图说明了阿里云 FaaS 产品的核心优势:

2. 无服务计算应用场景

**

前面探讨了无服务计算的优势,那么无服务计算都有哪些典型的应用场景呢?

在此分享笔者之前在项目中构建无服务应用的两个案例:

  • 云端视频转码:

    • 技术方案:设备端捕获短视频,上传到云端存储(例如阿里云 OSS),云端存储监测到文件上传后触发无服务计算函数函数,函数中调用 FFmpeg 给视频加水印、加特效,将视频转码后再转存到云端存储上,同时通知业务服务更改视频状态。
    • 方案优势:设备端视频上传频率很不稳定,可能有一段时间所有设备空闲,也有可能某一段时间几千台设备同时上传,而视频转码是比较消耗资源的,如果通过普通服务器提供转码能力并要确保所有视频都能在预期时间内转码完成的话,必须按最高并发量配置服务器资源,这些服务器成本是相当可观的。即使云服务器采用 Auto Scalling 策略,也需常备部分服务器,无法做到不使用时零运行成本,而且云服务 Auto Scalling 触发及启动时间也是分钟级的,很难达到服务能力秒级快速伸缩。
  • 物联网设备监控:
    • 技术方案:设备端通过云原生 IoT 服务上报状态,云原生 IoT 服务收到消息后触发无服务计算函数,函数中对 IoT 原始消息做简单清洗后转发到后端服务做进一步业务处理,例如:发推送消息给设备管理 App,当然也可以通过函数将 IoT 消息转存到 NoSQL 数据库。
    • 方案优势:端侧设备活跃时间不固定,如果想通过其他后端服务监控设备状态, 该服务必须保持 7*24 小时在线,架构和应用都需要确保高可用。而且设备并发量也是不稳定的,要考虑服务伸缩架构。还有一点需要考虑的是,云端资源通过事件或者规则直接唤起无服务计算函数比价方便,只需要简单配置即可,而对接自定义服务则要复杂得多。

基于项目经历以及个人理解,笔者认为无服务计算主要有以下几种典型的应用场景:

  • 可分解成独立运行单元的 CPU 密集计算型任务;
  • 构建弹性伸缩 Web 后台应用;
  • 无缝粘合调度云上资源;
  • 快速低成本上线敏捷应用。

3. 无服务计算不适合做什么

**

前面列举了很多无服务计算的优点以及运用在一些场景中的好处,很多人肯定觉得无服务计算太好用了,太想用了,这个场景能否用无服务计算?那个业务能否用无服务计算代替?

这里笔者可能要先泼一瓢冷水:无服务计算很好用,但不一定处处好用。当然这瓢冷水以及接下来的一些总结只是基于个人理解, 欢迎拍砖。

个人认为无服务计算其实只适合应用在一些逻辑相对简单、外部依赖相对较少、不需要复杂编排治理、没有极致性能要求的业务,主要原因如下:

  • 无服务计算在服务编排以及服务治理方面是比较弱的,虽然主流云厂商都提供无服务计算的函数编排产品(例如阿里云的 Serverless 工作流,AWS 的 Step Functions 等),但想要实现函数的限流降级、调用链追踪、自动注册发现等比较复杂的编排治理以及可探测性还是需要做很多额外的工作,弥补这些不足所要做的工作远大于无服务计算本身节省的工作量。这点也是和无服务计算无需运维、配置简单、开箱即用的思想是背道而驰的。
  • 无服务计算应用运行所依托的底层服务器以及运行环境对用户是透明的,用户无法选择,也无法优化。例如在笔者之前的视频转码方案中,有些特效处理如果运行在 GPU 服务器上是可以大幅加速的,但是在无服务计算中只能依靠 CPU 计算。
  • 无服务计算程序运行的环境是高度标准化的,有些依赖于特定运行环境、特定服务器版本、甚至特定硬件资源的依赖是很难确保兼容性的。如果有些应用尤其是原有技术资产受到运行环境制约的话,尽量还是回归到传统的云服务器部署方案。
  • 无服务计算的弹性伸缩并非没有上限,和普通应用一样,无服务应用在实际生产系统中也需要考虑并发达到上限的情况。虽然所有厂商的无服务计算产品都能根据并发量弹性伸缩,但这个弹性本身还是靠底层硬件资源支撑的,一般来讲各厂商的无服务计算产品都会有默认的并发上限设置,虽然通过工单申请可以调整,但也不能调整为无限量。如果账号下有多个无服务应用,需要对不同应用做的流量分配或者限制,并且考虑某一应用访问流量达到并发上限的情况。

4. 无服务能否替代微服务

**

笔者认为这两者应该不是一个维度的概念,微服务更多的是一种服务构建的架构思想,而无服务更偏重于一种服务部署和运行的技术方案,例如:微服务架构中某一个接口是可以通过无服务方式实现的。

当然,涉及到具体技术层面,通过 SpringCloud 或者 Dubbo 对外提供 RESTful 接口服务,还是将无服务函数挂载到 API 网关下对外提供 RESTful 服务,这两种技术方案确实是可以放到一起比较的。至于选择哪种技术实现,个人认为主要取决于运用场景和业务复杂度,前面总结了无服务计算的优势和不一定那么好用的场景。下面是个人的建议:

  • 如果应用中需要复杂的服务编排、服务治理、调用链追踪、统一的配置管理、自动注册发现等能力,建议还是采用“传统的”微服务技术方案;
  • 相反,如果只需要构建一个“短平快”的应用,采用无服务计算方案会让你好体验到极大的便利。正如笔者接下来将要分享的案例,就是采用无服务技术构建一个简单的 Web 后台应用。

阿里云 FaaS 实战

前面谈了比较多抽象的概念和看法, 下面结合笔者经历的一个实际案例展示如何使用阿里云 FaaS 产品构建一个无服务应用,尤其是实现 FaaS 应用的自动构建、自动部署。

1. 项目背景介绍

**

某外企客户需要将一个为用户提供产品咨询的服务从某友商无服务平台迁移到阿里云 FaaS。这个应用原部署于友商海外平台,基于 Nodejs 开发,通过 API Gateway 暴露 RESTful 接口,数据存储采用友商云原生 NoSQL 数据库。

迁移改造主要涉及以下三部分工作:

  • 阿里云产品适配选型
  • 代码逻辑改造
  • 应用部署工具选择及脚本编写

其中第三部分构建、部署脚本改造是此次迁移工作的重点,接下来逐一展开说明。

2. 阿里云产品适配选型

**

友商的无服务计算及网关在阿里云上均有对应产品,在此不展开比较。

友商云原生 NoSQL 数据库为该平台独有产品,经过和客户讨论认为,完全可以用其他 NoSQL 产品代替,加之现有开发人员更熟悉 MongoDB 技术栈,最后数据存储选型为阿里云云原生 MongoDB。

以下为整体迁移方案示意图:



**

3. 代码逻辑改造

**

用户编写无服务应用代码时,原则上只需要关注代码逻辑即可,主体代码逻辑部分大体上差异不大,比较明显的差异主要体现在事件处理入口函数写法上。参考FaaS 代码示例改造针对 API 网关事件的处理函数:

  1. module.exports.handler = function(event, context, callback) {
  2. var response = {};
  3. callback(null, response);
  4. };

4. 应用部署工具选择及脚本编写

**

  • 应用构建及部署工具选择

客户原来采用第三方工具 Serverless (https://www.serverless.com/) 实现无服务计算应用的构建和部署。Serverless 框架虽然宣称支持几乎所有主流云厂商的无服务产品,但经过调研后发现其对某友商支持是最全面的,有很多代码示例或者工程脚手架,几乎是开箱即用。但该工具对阿里云的支持比较有限,示例也相对较少。经过评估,我们决定采用阿里云自己的工具 Funcraft。

Funcraft 如何安装配置请参考产品文档,此处不展开讨论。接下来主要展示如何通过 Funcraft 脚本实现服务、函数、网关、日志、鉴权等相关资源的部署及配置。

  • 编写脚本

编写脚本前,先看一下目标系统的部署架构以及 Funcraft 要实现的功能蓝图:

Funcraft 脚本及配置说明详见以下代码:

  1. yaml
  2. ROSTemplateFormatVersion: '2015-09-01'
  3. Transform: 'Aliyun::Serverless-2018-04-03'
  4. Resources:
  5. demoService: #资源名称, 根据需要命名
  6. Type: 'Aliyun::Serverless::Service'
  7. Properties: #属性设置
  8. Description: 'This is a faas demo ' #资源描述
  9. Policies: #安全策略,系统自动根据策略为函数创建角色
  10. - AliyunOSSFullAccess
  11. - AliyunRAMFullAccess
  12. - AliyunLogFullAccess
  13. - AliyunApiGatewayFullAccess
  14. - AliyunFCFullAccess
  15. - AliyunMongoDBFullAccess
  16. - AliyunVPCFullAccess
  17. - AliyunECSNetworkInterfaceManagementAccess #特别说明,配置此策略才能创建弹性网卡进而打通函数以及VPC内连接
  18. VpcConfig: #允许函数访问的VPC配置
  19. VpcId: 'vpc-xxxxxx'
  20. VSwitchIds: ['vsw-xxxxxx']
  21. SecurityGroupId: 'sg-xxxxxx'
  22. LogConfig: #日志服务配置
  23. Project: sls-demo
  24. Logstore: logstore-demo
  25. demoFunction: #函数名称
  26. Type: 'Aliyun::Serverless::Function' #资源类型为服务,服务内可以挂载多个函数
  27. Properties:
  28. Handler: index.handler #事件处理入口
  29. Runtime: nodejs10 #程序运行环境
  30. CodeUri: './src' #程序代码相对于当前脚本的路径
  31. EnvironmentVariables: #环境变量设置,
  32. MONGO_URL: mongodb://userx:pwdx@dds-xxx.mongodb.rds.aliyuncs.com:3717/demoDb #Mongo内网连接地址
  33. RESULT_TABLE_NAME: demo_table
  34. demoGroup: # Api Group
  35. Type: 'Aliyun::Serverless::Api' #资源类型为API,每个API分组下可以挂载多个API接口
  36. Properties:
  37. StageName: RELEASE #发布环境
  38. DefinitionBody:
  39. '/v1/recommendervera/[resultId]': # request path
  40. get: # http method
  41. x-aliyun-apigateway-api-name: demo_api # api name
  42. x-aliyun-apigateway-fc: # 当请求该 api 时,要触发的函数,
  43. arn: acs:fc:cn-shanghai:xxx:services/demoService.LATEST/functions/demoFunction
  44. timeout: 3000
  45. x-aliyun-apigateway-request-parameters: #设置参数类型
  46. - apiParameterName: 'resultId'
  47. location: 'Path' #传参方式,此处为在URI请求路径中传餐
  48. parameterType: 'String'
  49. required: 'REQUIRED' #设置为必选参数
  50. '/v1/recommendervera/': # request path
  51. post: # http method
  52. x-aliyun-apigateway-api-name: demo_api_post # api name
  53. x-aliyun-apigateway-fc: # 当请求该 api 时,要触发的函数,
  54. arn: acs:fc:cn-shanghai:xxxx:services/demoService.LATEST/functions/demoFunction
  55. timeout: 3000
  56. x-aliyun-apigateway-auth-type: APP #设置鉴权类型,此处设置为简单的APP code类型鉴权
  57. x-aliyun-apigateway-app-code-auth-type: HEADER #鉴权加密方式,此处设置为通过Header传递授权后的app
  • 资源准备

服务、函数、API 网关都可以通过以上Funcraft 脚本一站式创建完成,日志、MongoDB、鉴权所需应用等外部资源需要提前创建或者配置好。

这里特别要说明的是:函数通过内网链接 MongoDB 时,需要通过配置允许函数访问 MongoDB 所在 VPC 及交换机,并为函数访问创建一个独立的安全组用于配置弹性网卡,并且将此安全组加入到 MongoDB 的白名单中,进而打通函数计算与 VPC 之间的网络联通。

前面提到的 VPC、交换机以及安全组已经提前创建好并配置在 Funcraft 脚本中了,下面看看在实际的 MongoDB 资源中如何配置白名单安全组:



**

5. 构建和部署

以上脚本资源都准备好后,就可以执行 fun build 命令进行构建了。构建时,工具会读取指定代码目录下的 package.json 文件加载相关插件依赖及配置。

构建执行命令示例:

  1. bash
  2. $ fun build
  3. using template: template.yml
  4. start building function dependencies without docker
  5. building demoService/demoFunction
  6. running task: flow NpmTaskFlow
  7. running task: CopySource
  8. running task: NpmInstall
  9. Build Success
  10. Built artifacts: .fun/build/artifacts
  11. Built template: .fun/build/artifacts/template.yml
  12. Tips for next step
  13. ======================
  14. * Invoke Event Function: fun local invoke
  15. * Invoke Http Function: fun local start
  16. * Deploy Resources: fun deploy

构建完成后, 执行 fun deploy 命令部署到云端。示例如下:

  1. bash
  2. $ fun deploy
  3. using template: .fun/build/artifacts/template.yml
  4. using region: cn-shanghai
  5. using accountId: ***********3452
  6. using accessKeyId: ***********1fap
  7. using timeout: 60
  8. Collecting your services information, in order to caculate devlopment changes...
  9. Resources Changes(Beta version! Only FC resources changes will be displayed):
  10. ┌──────────────┬──────────────────────────────┬────────┬──────────────────────┐
  11. Resource ResourceType Action Property
  12. ├──────────────┼──────────────────────────────┼────────┼──────────────────────┤
  13. Description
  14. ├──────────────────────┤
  15. Policies
  16. demoService Aliyun::Serverless::Service Add ├──────────────────────┤
  17. VpcConfig
  18. ├──────────────────────┤
  19. LogConfig
  20. ├──────────────┼──────────────────────────────┼────────┼──────────────────────┤
  21. Handler
  22. ├──────────────────────┤
  23. Runtime
  24. demoFunction Aliyun::Serverless::Function Add ├──────────────────────┤
  25. CodeUri
  26. ├──────────────────────┤
  27. EnvironmentVariables
  28. └──────────────┴──────────────────────────────┴────────┴──────────────────────┘
  29. ? Please confirm to continue. Yes
  30. Waiting for service demoService to be deployed...
  31. make sure role 'aliyunfcgeneratedrole-cn-shanghai-demoService' is exist
  32. role 'aliyunfcgeneratedrole-cn-shanghai-demoService' is already exist
  33. attaching policies ["AliyunOSSFullAccess","AliyunRAMFullAccess","AliyunLogFullAccess","AliyunApiGatewayFullAccess","AliyunFCFullAccess","AliyunMongoDBFullAccess","AliyunVPCFullAccess","AliyunECSNetworkInterfaceManagementAccess"] to role: aliyunfcgeneratedrole-cn-shanghai-demoService
  34. attached policies ["AliyunOSSFullAccess","AliyunRAMFullAccess","AliyunLogFullAccess","AliyunApiGatewayFullAccess","AliyunFCFullAccess","AliyunMongoDBFullAccess","AliyunVPCFullAccess","AliyunECSNetworkInterfaceManagementAccess"] to role: aliyunfcgeneratedrole-cn-shanghai-demoService
  35. attaching police 'AliyunECSNetworkInterfaceManagementAccess' to role: aliyunfcgeneratedrole-cn-shanghai-demoService
  36. attached police 'AliyunECSNetworkInterfaceManagementAccess' to role: aliyunfcgeneratedrole-cn-shanghai-demoService
  37. Waiting for function demoFunction to be deployed...
  38. Waiting for packaging function demoFunction code...
  39. The function demoFunction has been packaged. A total of 1675 files were compressed and the final size was 2.1 MB
  40. function demoFunction deploy success
  41. service demoService deploy success
  42. Waiting for api gateway demoGroup to be deployed...
  43. URL: GET http://xxx-cn-shanghai.alicloudapi.com/v1/recommender/[resultId]
  44. stage: RELEASE, deployed, version: 20200715144450426
  45. stage: PRE, undeployed
  46. stage: TEST, undeployed
  47. URL: POST http://xxx-cn-shanghai.alicloudapi.com/v1/recommender/
  48. stage: RELEASE, deployed, version: 20200715144453967
  49. stage: PRE, undeployed
  50. stage: TEST, undeployed
  51. api gateway demoGroup deploy success

脚本正常执行后,可以在云端看到相关函数及 API 已经部署完成并且可以正常运行了。



接下来可以将以上 Funcraft 命令及脚本可以加入到 Jenkins、Gitlab 等工具流水线中,结合代码版本管理工具实现函数应用的持续集成、持续发布。

总结

随着无服务计算产品和技术的进一步成熟,会有越来越多的用户选择无服务计算技术;随着阿里云的进一步发展壮大,也会有越来越多用户采用阿里云 FaaS 构建无服务应用。

本文探讨了无服务计算的应用场景,并且结合实际应用案例,讲解了如何用 FaaS 构建无服务 Web 后台应用,并实现自动构建、自动部署,希望以上探讨和经验能够帮到大家。

作者简介

宋文龙,花名闻可,阿里云全球技术服务部高级交付专家,有多年云原生应用开发架构经验以及多年高性能服务器研发经验。目前专注于运用阿里云中间件技术、结合阿里巴巴中台架构经验为客户构建符合行业需要的业务中台解决方案并完成交付。

无服务计算应用场景探讨及 FaaS 应用实战的更多相关文章

  1. Serverless的概念&定义-无服务计算详解

    过去几年间,Serverless 发展迅猛,与其相伴的还有从小程序.移动端等到前后端一体化的演进与实践,也正因如此,从云计算到前端,众多开发者都极为关注 Serverless到底是什么? 在国内,Se ...

  2. 无服务架构在IOT的应用场景——使用函数工作流处理DIS数据

    在物联网领域,复杂性往往并非在于传感器,真正的复杂性在于各种传感器产生的大量数据,以及对这些数据的处理,所以开发者不得不花费大量的时间去构建和维护后端服务器来处理这样一个庞大的数据流.而在今天这个敏捷 ...

  3. 什么是Docker—无服务器计算服务

    什么是Docker https://mp.weixin.qq.com/s?__biz=MzU0Mzk1OTU2Mg==&mid=2247483881&idx=1&sn=aa27 ...

  4. 理解serverless无服务架构原理(一)

    阅读目录 一:什么是serverless无服务? 二:与传统模式架构区别? 三:serverless优缺点? 四:使用serverless的应用场景有哪些? 回到顶部 一:什么是serverless无 ...

  5. 理解serverless无服务

    理解serverless无服务 阅读目录 一:什么是serverless无服务? 二:与传统模式架构区别? 三:serverless优缺点? 四:使用serverless的应用场景有哪些? 回到顶部 ...

  6. Serverless无服务应用架构纵横谈

    Serverless无服务应用架构纵横谈 一.Serverless是啥 自从互联网兴起以来,Server就成了网络的核心部件.所以围绕Server的生意圈,也发展得如火如荼. 从最早的电信托管,到虚拟 ...

  7. 5分钟构建无服务图片鉴黄web应用(基于FunctionGraph)

    函数工作流(FunctionGraph,FGS)是一项基于事件驱动的函数托管计算服务,托管函数具备以毫秒级弹性伸缩.免运维.高可靠的方式运行.即使在一些复杂的web应用场景中,函数工作流也能发挥出令人 ...

  8. 《Serverless架构-无服务单页应用开发》读后感

    本书的作者是[美]Ben Rady,译者郑赞美.简传挺,书中作者详细的介绍了如何使用html.js以及amazon提供的诸多云服务(Simple Storage Service(S3).Cognito ...

  9. SOA之(3)——面向服务计算基础

    面向服务计算基础(Service-Oriented Computing Fundamentals) 面向服务的计算(Service-Oriented Computing) 面向服务的计算是一个伞状术语 ...

随机推荐

  1. Unable to instantiate org.apache.hadoop.hive.ql.metadata.SessionHiveMetaStoreClient

    1.今天在进行hive测试的时候,发现hive一直进不去,并且报了这个错误. Unable to instantiate org.apache.hadoop.hive.ql.metadata.Sess ...

  2. java的stream的使用

    过滤 filter: //匹配第一个元素 Optional<Integer> findFirst=list.stream().filter(x->x>6).findFirst( ...

  3. eh-admin一套前后端一体的轻量级后台管理系统

    https://gitee.com/DawnYang/eh-admin 主要技术 后端技术:Spring Boot,Apache Shiro,MyBatis-Plus等: 前端技术:Jquery,La ...

  4. Adaptive AUTOSAR 学习笔记 16 - 时间同步和网络管理

    本系列学习笔记基于 AUTOSAR Adaptive Platform 官方文档 R20-11 版本 AUTOSAR_EXP_PlatformDesign.pdf.作者:Zijian/TENG 原文地 ...

  5. gimp 缩放图片 python script

    滤镜 -> Python Fu -> 控制台,复制粘贴下面代码. 然后 scale_image(800, 800) 图片自动缩放为 800*800 了 这个代码是傻傻的缩放,你可以把它改成 ...

  6. 2021-06-14 BZOJ4919:大根堆

    BZOJ4919:大根堆 Description: 题目描述   给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切地说,你 ...

  7. Appium问题解决方案(5)- selenium.common.exceptions.InvalidSelectorException: Message: Locator Strategy 'name' is not supported for this session

    背景 使用Appium Server 1.15.1版本 执行了以下脚本 test = driver.find_element_by_name("自动化测试") print(test ...

  8. Spring MVC拦截器浅析

    Spring MVC拦截器 重点:Spring MVC的拦截器只会拦截控制器的请求,如果是jsp.js.image.html则会放行. 什么是拦截器 运行在服务器的程序,先于Servlet或JSP之前 ...

  9. session案例之验证码

    一.需求分析 其中,一张图片就是一个单独的请求: 一个验证验证码的Servlet,还有一个验证用户名和密码的Servlet,两次都可能有错误信息返回到前端页面,所以前面页面要从request域中获取返 ...

  10. python库--requests

    requests 方法 返回 参数 方法详情 .get()  r  url  get请求 params  url?后面的内容会以'key=value'的方式接到url后面 proxies 设置代理ip ...