Skip to content

Serverle 应用开发进阶

1.性能优化:Serverle 应用的性能提升

前言

Serverless 自动弹性伸缩的特性让应用具备了无限扩展的能力,但基于 FaaS 的实现也带来了一个很大的副作用,即冷启动

冷启动是代码在处理业务功能之前的额外开销

Serverless 的性能优化的核心就是:减少冷启动

  • 深入理解冷启动
  • 如何优化 Serverless 的性能

深入理解冷启动

  • 链路追踪
  • 压测

深入理解冷启动,是优化 Serverless 应用性能的前提

函数的启动过程示意图

图中可以看出:冷启动需要经过多个步骤,耗时比较长

通过链路追踪功能,可以检测冷启动耗时,有以下工具

  • AWS 的 X-Ray
  • 阿里云的链路追踪
  • Lambda
  • 函数计算

函数计算链路追踪截图

函数计算链路追踪截图

  • InvokeFunction:函数执行总时间
  • ClodStart:是函数冷启动时间
  • PrepareCode:是函数冷启动过程中下载代码或下载自定义镜像的时间
  • Runtimelnitialize:是执行环境启动的时间包括启动容器和函数运行环境
  • Invocation:是执行函数的时间

什么时候函数是冷启动或者热启动呢?

函数第一次执行的时候一定是冷启动,但后面的请求不一定都是热启动这与触发函数执行的事件是串行还是并行有关

在接口请求抓包拦截器中(如),对一个接口发起请求 100 次,这种属于串型请求,在请求结果中可以看到,第一个请求最长时间,后面时间就短了,所有第一个请求是冷启动,后面的请求都属于热启动

如果同时对 10 个并行访问 100 次,那么前 10 个请求都是冷启动,请求时间较长,后面的请求便是热启动

业务例子

  • 团购订餐业务,可能在每天中午、晚上流量突增
  • 促销活动,在活动开始前流量突增
  • 社交软件,遇到重大新闻时流量突增

流量突增就意味着 FaaS 平台不得不添加更多的实例来支持更大的并发,并且新增实例时都会有冷启动,这就对用户体验有较大影响了

如何优化 Serverless 的性能

1.避免函数冷启动

  • 对函数进行预热
    • 预热就是指你通过定时任务,在真实请求到来之前,对函数发起请求使函数提前初始化
    • 是否使用预热的方案,既要考虑业务场景,也要平衡性能和成本如果你的应用对延迟要求很高,比如秒杀业务,就可以使用预热功能.
  • 使用预留资源
    • 此外有些 FaaS 平台 (比如函数计算) 也提供了预留资源的功能,可以为你的函数实例持续保留

2.减小代码体积

函数冷启动的第一个步骤就是下载代码

减少代码体积,可以避免引入不必要的依赖、不要加载不需要的代码对 SDK 进行精简、对代码进行压缩,甚至只构建需要执行的代码

3.提升函数吞吐量

大多 FaaS 都支持了单实例多并发

单实例多并发

单实例单并发图例

单实例单并发

单实例多并发图例

![单实例多并发 (2)](.\img\单实例多并发 (2).jpg)

4.选择合适的编程语言

冷启动耗时:

Java 比 Node.js、Python 等耗时要多

选择冷启动时间短的编程语言,可以大幅提升应用性能

有人测试过

  • 函数计算中:PHP 冷启动最快 Node.js、Python 次之,Java 最慢
  • Java 冷启动耗时:大约是 Nodeis 或 PHP 的三倍,Node.js、Python、PHP 的冷启动耗时基本在 1s 内
  • 随着内存增加,冷启动耗时逐渐缩短
新的性能优化方案

尽量选择 Node.is、Pvthon、PHP 等冷启动耗时短的语言编程

为函数设置合适的内存,内存越大,冷启动耗时越短,但成本也越高。所以要设置一个合适的内存

性能优化总结

Serverless 应用的性能优化,主要是围绕冷启动进行的,也可以针对代码运行时进行优化

Serverless 性能优化的一些实践方案

  • 1.提前给函数预热
  • 2.使用预留资源
  • 3.减小代码体积减少不必要的依赖
  • 4.执行上下文重用
  • 5.为函数设置并发
  • 6.选择冷启动耗时少的编程语言
  • 7.为函数设置合适的内存

2.访问控制:授权访问其他云服务

前言

  • 1.权限问题:直接使用具有 AdministratorAccess 权限的访问凭证去部署应用甚至管理云资源这是非常不安全的
  • 2.当企业规模逐渐变大,企业中有不同角色的成员,为了云上资源的安全性,你就需要为不同角色配置不同权限,限制不同成员能够访问的云资源

对于访问控制,各个云厂商都有相应的产品

  • aws-IAM:AWS Identity and Access Management
  • 阿里云-RAM:Resource Access Management

不同云厂商的实现细节可能有所差异,但工作原理基本一致

访问控制的工作原理

如果你是一个云产品的架构师,那你要怎么设计一个访问控制系统,实现这样几个很常见的需求呢?

分权

如何使不同成员拥有不同的权限?

比如运维同学才能购买云产品,Serverless 开发同学只能使用 Serverless 产品而不能购买,财务同学只能使用费用中心查看账单等

云服务授权

如何使云服务能够访问某个云资源?

比如只允许函数计算读对象存储中的文件,而不能删除或创建

跨账号授权

如何使其他账号能够访问你的云资源?

比如某个大型企业有两个云账号其中一个云账号 A 是用来开发生产的,另一个 B 用于审计,存储所有日志那么 A 如何使用 B 里面的日志?

通过子账号、角色和权限策略来实现云上的访问控制

通过子账号、角色和权限策略来实现云上的访问控制

子账号创建完成后,有两种使用方式
  • 控制台访问:通过子账号登录控制台管理云资源
  • 编程访问:在代码中使用子账号的 AK 来调用云产品的 AP 进而管理云资源

当我们资源数量越来越多时通常会通过编程的方式来使用和管理云资源

1.不安全:AdministratorAccess ==> 子账号 AK
2.角色授权:角色是一个虚拟用户,必须被某个具体用户 (子账号、云服务等) 扮演使用,可以通过添加权限策略为角色授权同时创建角色时,需要指定角色能够被谁扮演,即角色的可信实体

角色用户授权

基于角色扮演的方式,你就可以实现云服务授权跨账号授权

3.通过权限策略给用户或角色授权

JSON 字符串授权,通过以下

  • 系统策略
  • 云服务权限 => 自定义策略

阿里云 AdministratorAccess 的权限策略

json
{
	"Statement": [
		{
			"Action": "*",
			"Effect": "Allow",
			"Resource": "*"
		}
	],
	"Version": "1"
}

只读 OSS 的系统权限策略 AliyunOSSReadOnlyAccess 配置

json
{
	"Statement": [
		{
			"Action": ["oss:Get*", "oss:List*"],
			"Effect": "Allow",
			"Resource": "*"
		}
	],
	"Version": "1"
}

访问控制的场景案例

使用最小权限的子账号部署函数

为什么要限制权限呢?

如果给开发同学的 AK 权限过大开发者不小心的操作就很可能会对其他正在运行的云服务造成验证影响比如不小心删除了数据库

建议专门为 Serverless 应用开发创建一个子账号

![专门为 Serverless 应用开发创建一个子账号](.\img\专门为 Serverless 应用开发创建一个子账号.jpg)

自定义策略

json
{
    "Statement": [
  {
         "Effect": "Allow",
            "Action": [
                "fc:GetService",
                "fc:UpdateService"
            ],
      "Resource": [
                "acs:fc:cn-beijing:*:services/serverless-app'
            ]
        },
        {
            "Effect":"Allow",
            "Action": [
                "fc:*"
            ],
            "Resource": [
                "acs:fc:cn-beijing:*:services/serverless-app/functions/*"
            ]
        }
    ],
    "Version": "1"
}

有些开发框架,它们允许你通过 YAML 去配置其他云服务并且在你部署时会自动帮你创建或更新这些服务

使用日志服务存储函数的日志

使用日志服务存储函数的日志

创建 RAM 角色

![创建 RAM 角色](.\img\创建 RAM 角色.jpg)

在 A 账号的函数中访问 B 账号的 OSS 文件可以通过角色扮演来实现第三个场景

创建场景略...

图例

角色扮演

代码

js

授权访问其他云服务总结

介绍了云上访问控制的基本工作原理,以及在实际开发中的场景案例

云上的访问控制

  • 云厂商主要通过主账号、角色、权限策略等方式来实现云上资源的访问控制
  • 通过访问控制,能实现分权、云服务授权、跨账号授权等云上资源管控需求
  • 实际工作中,对于用户访问权限要遵循最小授权原则

3.安全生产:提高 Serverle 应用的安全性

前言

安全问题

Serverless 是否安全取决于怎么去做虽然本质上应用会更安全但这建立在你正确地进行架构设计、代码实现的基础上

希望你能提高安全意识,掌握这份安全生产指导手册

Serverless 安全问题

  • Serverless 安全面临的挑战
  • Serverless 安全的主要风险
  • 如何提升 Serverless 的安全性

Serverless 安全面临的挑战

从软件开发的角度来看

提供 Serverless 服务的云厂商

  • 专注产品功能的实现

  • 无须为服务和操作系统安装安全补丁

  • 完全不用考虑底层服务器操作系统以及软件运行环境

角色负责要点

面对的挑战

  • 攻击面越来越广
    • 由于 Serverless 中函数的数据来自多种数据源,这就极大增加了攻击面,特别是当数据源消息结构非常复杂时,传统的 Web 防火墙方式就很难对数据进行校验
  • 攻击方式越来越复杂
    • 除了传统的 DDoS 攻击、数据注入等攻击方式,Serverless 还面临着事件注入、流程劫持等新的攻击方式
  • 可观测性不足
    • 因为 Serverless 对开发者来说是屏蔽了底层基础设施,且应用是由分布式的函数组成,所以 Serverless 应用的可观测性比传统应用更复杂
  • 传统安全测试方法不适用
    • 当 Serverless 应用依赖了第三方服务或云服务,虽然在单元测试时这些依赖可以被模拟,但进行安全测试却不能模拟
    • 传统的安全测试工具对 Serverless 应用也不适用
      • DAST:主要是扫描 HTTP 接口进行安全测试
      • SAST:这类工具主要是通过分析代码语法、结构、接口、控制流等来检测程序等漏洞
      • IAST:这类工具通过将流量代理到测试服务器等方式进而可以得到更高的准确率、更低的误报率
  • 传统安全防护方案不兼容
    • 基于 Serverless 应用,没有办法访问物理机和虚拟机,所以,没有办法考虑传统的安全层,比如端点防护,web 防火墙等。大多数传统安全防护方案与 Serverless 架构不兼容

Serverless 安全的主要风险

1.函数事件注入2.身份认证无效3.应用配置不安全4.用户或角色权限过高5.函数日志和监控能力不足
6.第三方依赖不安全7.敏感信息泄漏8.DDoS 和资损9.函数执行流程操纵10.错误处理不当
  • 函数事件注入

    • 数据注入是最常见的安全风险不过在传统应用中,这些数据注入都是用户输入的数据而 Serverless 应用的数据并不局限于用户输入
    • 丰富的数据源
  • 身份认证无效

    • Serverless 架构的应用是由几十甚至上百个函数组成,每个函数实现特定的业务功能,这些函数组合完成整体业务逻辑。一些函数可能会公开其 Web API,需要进行身份认证。另一些则可能只允许内部调用,所以不用进行身份认证
    • 身份认证无效
  • 应用配置不安全

    • 在云上运行的应用,尤其是 Serverless 应用,经常会使用到很多应用配置
    • 另外你还会基于配置来实现环境区分、功能开关等逻辑
    • 对于配置中心或存放应用配置的云存储授权不当,这很可能造成应用敏感信息泄露,或没有权限的用户不小心修改配置导致应用无法运行
  • 用户或角色权限过高

    • Serverless 应用应该秉持最小权限的原则,也就是仅给函数提供其执行时所必需的权限
    • 很多开发者或团队为了方便,就为函数设置了统一的较大的权限,如果一个应用中函数权限过高,那单个函数的漏洞就可能造成系统级灾难
  • 函数日志和监控能力不足

    • 虽然云厂商都对函数提供了日志和监控功能,但这些工具都很新,提供的能力也有限,要想利用这些工具来可视化 Serverless 架构的运行情况还非常困难
    • 函数日志和监控能力的不足,就会导致面临攻击时,你就很难针对 Serverless 攻击进行报警,也很难通过日志去分析、排查并解决问题
  • 第三方依赖不安全

    • 很多时候为了完成业务逻辑,函数就要依赖第三方软件包、开源库,甚至通过 API 调用第三方远程 Web 服务如果函数的第三方依赖不安全,也很可能导致函数不安全
  • 敏感信息泄露

    • 随着应用规模和复杂性的增长,应用需要维护越来越多的敏感信息
    • 比如访问凭证 (AccessKevld、AccessKeySecret 和 SecrityToken)、数据库密码、加密密钥等
    • 常见的错误做法是:把这些敏感信息简单地放在项目配置文件中,随代码一起上传
  • DDoS 和资损

    • DDoS 几乎成了每个暴露在互联网上的服务面临的主要风险之一比如大量恶意运行函数造成资损

    • 如这一段解析出漏洞数据的代码:攻击者对这段函数发起大量请求,这段函数执行不完,便会被强制停止,执行太多次,费用也会增加

      js
      module.exports.parse = (event, spotText) => {
      	// 从 Content-Type 中获取 boundary 属性
      	const boundary = getValuelgnoringKeyCase(
      		event.headers,
      		"Content-Type"
      	).split("=")[1];
      
      	// 根据 boundary 从消息体中解析数据
      	const body = (
      		event.isBase64Encoded
      			? Buffer.from(event.body, "base64").toString("binary")
      			: event.body
      	)
      		.split(new RegExp(boundary))
      		.filter((item) => item.match(/Content-Disposition/));
      };
  • 函数执行流程操纵

    • 通过操纵函数执行流程,攻击者可以破坏应用逻辑 并且还可以利用该方式绕过访问控制、提升用户权限、甚至发起 DDoS 攻击 Serverless 应用是由很多离散的函数组成,这些函数按特定顺序编排到一起,形成整体应用
    • 攻击逻辑:恶意上传大量文件 攻击逻辑:恶意上传大量文件
  • 异常错误处理不当

    • 由于 Serverless 的调试方式还比较有限 所以很多开发者喜欢直接在 FaaS 平台上打印函数运行时的日志,以及长的错误信息 如果一些敏感信息没有被清除,可能导致敏感信息泄露在日志中 或日志中记录了详细的错误堆栈,暴露代码的漏洞

Serverless 安全总结

  • 在云上运行的应用,云厂商负责计算、网络、存储等底层资源的安全性应用所有者负责应用本身的安全性
  • Serverless 安全性面临的主要挑战是:越来越多的攻击面、越来越复杂的攻击方式可观测性不足以及传统安全测试方法和防护方案不适用于 Serverless 架构
  • 对于 Serverless 架构的安全风险需要深入理解,才能更好地规避

如何提升 Serverless 的安全性

一、正确编程,减少应用的代码泄漏

  • 1.不要相信任何用户输入
    • 由于 Serverless 应用的攻击面更多,攻击手段更复杂所以你永远不要相信任何输入,也不能对输入进行有效性假设
  • 2.使用安全的第三方依赖
    • 维护项目的依赖及版本
    • 扫描依赖项找出并去掉存在漏洞的版本
    • 删除不必要的依赖
    • 仅从可信赖的资源中使用第三方依赖
    • 将不推荐使用的依赖更新到最新版本
  • 3.可以从一些公开的安全漏洞披露平台中浏览某个依赖有没有安全漏洞
    • Nodejs 模块中的已知漏洞
    • Java 中的已知漏洞
    • Python 相关技术中的已知漏洞
  • 4.正确地处理程序异常
    • 对于生产环境中的代码,需要避免打印冗长的错误信息
    • 建议你只为用户提供简单的错误消息
    • 不要显示有关任何内部实现的堆栈或环境变量的详细信息
  • 5.通过 API 网关确保 API 安全
    • 使用 Serverless 最常见的场景之一就是构建 API
    • 通过API网关确保API安全

二、正确的使用访问控制

访问控制是使用云产品时非常重要的功能,尤其是在规模比较大的团队中,访问控制可以用来限制不同用户能够操作的资源

1.为用户和角色配置最小的权限

  • 为了减少访问凭证泄漏带来的风险,建议你使用访问控制来管理每个函数具有的权限,并确保每个函数都有且仅有运行时所需要的最小权限,也可以使用一些开源的工具来保证函数的最小权限

    2.使用临时访问凭证

  • 当使用代码对云产品进行编程访问时,就会用到访问凭证在 Serverless 函数中,建议你尽可能使用临时访问凭证而不是直接在代码中配置固定的访问凭证

固定访问凭证代码

js

临时访问凭证代码

js

三、增强数据安全防护

1.对云上的数据进行加密

云上的数据主要有两部分:云上存储的数据;云上传输的数据为了避免中间人攻击,导致传输过程中的数据泄漏建议你使用 TLS 协议对函数通信、网络请求等传输数据进行加密

2.对应用配置进行加密

几乎每个应用都会有很多配置这些信息会在不同的应用、代码、环境变量中进行传输只要其中有一个环节有漏洞,就会导致数据泄漏一定要避免在代码中定义明文配置,要对这些配置进行加密

如何对配置进行加密

  • AWS Secrets Manager
  • 阿里云密钥管理服务
  • Azure 密钥保管库
  • Google Cloud KMS
3.使用 Serverless 相关的身份认证服务

为了避免没有权限的用户访问数据你也需要对访问请求进行身份认证

Serverless 相关运行身份验证功能
  • AWS Cognito 或单点登录
  • AWS API Gateway
  • 阿里云 API 网关
  • 腾讯云 API 网关
  • Azure 应用服务身份认证和授权
  • Google Firebase 身份认证

四.提升应用可观测性

由于 Serverless 应用可观测性不足,遇到安全攻击可能难以第一时间发现,发现安全问题也难以快速定位并恢复,所以导致 Serverless 面临着比传统应用更大的安全风险

1.记录函数日志并设置报警

Serverless 屏蔽了底层机器需要将日志输出到统一的日志存储服务,这样才能更方便查看问题

强烈建议针对云账号的账单设置报警,尽可能避免预期外的费用

2.使用配置审计监控资源的配置变化

由于 Serverless 函数是在云上运行的,函数本身就有很多配置;函数依赖的云服务也有很多配置,一旦某个配置发生变化,很可能对应用运行造成影响。

建议使用云厂商提供的配置审计功能来检测云资源的配置变化

基于配置审计,持续监控的规则
  • 检测函数是否通过控制台创建
  • 检测使用同一个角色的多个函数
  • 检测配置了多个不同触发器的函数
  • 检测使用通配符(*)权限的函数
3.使用操作审计记录云上所有操作事件

如果某个用户误删或恶意删除了某个资源,你要及时收到报警并处理,尽可能避免影响变大

这时你就可以使用云厂商的操作审计服务了

Serverless 安全生产总结

1.Serverless 安全面临的挑战

  • 攻击面越来越广
  • 攻击方式越来越复杂
  • 可观测性不在
  • 传统安全测试方法不适用
  • 传统安全防护方案不适用

2.Serverless 安全的主要风险

  • 函数事件注入
  • 身份认证无效
  • 应用配置不安全
  • 用户或角色权限过高
  • 函数日志和监控能力不足
  • 第三方依赖不安全
  • 敏感信息泄漏
  • DDoS 和资损失
  • 函数执行流程操纵
  • 异常处理不当

3.如何提升 Serverless 的安全性

减少应用代码漏洞
  • 不要相信任何输入
  • 使用安全的第三方依赖
  • 正确处理程序异常
  • 通过 API 网关确保 API 安全
正确使用访问控制
  • 为用户和角色配置最小权限
  • 使用临时访问凭证
增强数据安全防护
  • 对云上数据进行加密
  • 对应用配置进行加密
  • 使用 Serverless 相关的身份认证服务
提升应用可观测性
  • 记录函数日志并配置报警
  • 使用配置审计监控资源的配置变化
  • 使用操作审计记录云上所有操作事件

4.成本管理优化:Serverless 应用的成本优化

前言

Serverless 应用的成本

  • 分析
  • 优化
  • 控制

对技术 Leader 来说,在进行技术选型时,除了考虑技术架构、稳定性等,更需要考虑成本

Serverless 应用的成本分析

函数一小时的费用比云服务器一小时的费用大约要高 2.5 倍?

大多数 FaaS 都是按照函数执行次数和函数执行消耗的内存来收费的

  • 执行次数:1.3 元/百万次
  • 执行时间(按量付费) :0.0110592 元/1GB-秒

假设函数在一小时内只运行一次消耗内存是 1GB,函数运行时间为 1 小时

bash
0.00000133 + 60 * 60 * 0.000110592 = 0.398元

存在两个误区:

  • Serverless 的收费包含了应用的系统管理功能
    • Serverless 函数则可以完全利用分配的 CPU 和内存
  • Serverless 的函数并不是持续运行的
    • 函数每次只会运行几十毫秒到几百毫秒,不运行时不收费所以实际产生的费用可能要便宜得多

而云服务是按照时间长度统一收费

假设你的网站每天处理 10 万个请求,每个请求处理时间大约为 100ms,每个函需要 1G 内存

bash
(0.00000133*100000 + 0.1 * 0.000110592 * 100000) * 30 = 37.16元

所以 Serverless 的价格要比传统 Serverful 便宜很多

  • 大型企业中除 20%的核心应用外,剩余 80% 的都是中长尾应用
  • 这些应用平均 QPS 远远低于 1,甚至一天也没有几个用户访问
  • 但传统的 Serverful 架构中又不得不为这些应用准备至少 2 台服务器
  • 使用 Serverless 则可以极大节省这部分成本

使用 Serverless 都能极大降低成本

  • Financial Engines:使用 AWS LambdaServerless--成本降低 90%
  • 微博:使用阿里云函数计算--成本降低 35%
  • 世纪联华:使用阿里云函数计算--成本降低 40%

使用 Serverless 你不用再为空闲服务器付费,也不用担心不可预测的负载,所以 Serverless 能大幅降低成本

使用一些云厂商提供的或开源的 Serverless 成本计算器

  • 阿里云函数成本计算器
  • aws 成本计算器
  • Serverless costs calculator

Serverless 这种用多少花多少的收费模式带来的缺点

很难预测具体会产生多少费用,云厂商通常也提供了预付费模式来解决这个问题

Serverless 应用的成本优化

Serverless 应用是按照代码执行次数、执行时间进行收费

bash
性能 = 时间 = 成本

1.为函数设置超时时间

避免函数因为异常而无限制地运行下去,导致成本的上升,比如设置 10 秒

2.为函数分配合适的内存

函数收费是按照 GB 每秒来收费的,所以内存越高,费用越高但通常内存越高,函数运行速度又更快

128 MB -- 200ms == 0.0000040948 元

1024 MB -- 20ms == 0.00000247784 元

3.减少函数的冷启动耗时

函数的冷启动会直接增加函数的执行时间,并且这部分时间是你的业务逻辑之外的耗时,所以减少函数的冷启动时间,可以帮你节省一大笔费用

具体看上面:性能优化--冷启动相关

4.减少外部慢 API 调用

通常调用外部 API 会涉及网络请求,如果外部 API 比较慢,函数执行过程就会阻塞,从而导致函数执行耗时增加,进而增加成本

依赖第三方 Oauth 进行身份认证 ==> 就近选择 OAuth 服务

5.为函数实例设置并发

不仅能提升函数性能,还能节省函数成本

单实例单并发成本

![单实例单并发 成本](.\img\单实例单并发 成本.jpg)

单实例多并发成本

单实例多并发成本

6.选择合适的计费方式

目前绝大部分 FaaS 平台都支持按量付费和预付费,可以根据应用特点选择合适的付费方式

降低成本

应用流量一直很高且比较平稳对延迟也比较敏感 ==> 预留模式 ==> 极大减少冷启动

日常测试或离线处理数据时函数可能是临时大量执行 ==> 按量付费 ==> 保持较高的资源利用率

预留资源图

预留资源

Serverless 应用的成本控制

很难理解云厂商提供的账单,里面经常会有一些预期之外的费用,基于 Serverless 架构,账单变得动态起来,费用难以预测

为什么 Serverless 账单难以预测呢?

  • 应用是弹性的,很难预测函数到底要执行多少次
  • 应用通常不仅仅包含 FaaS 的费用,还有其他组合使用的云产品的费用而这些费用可能比 Faas 的成本还高

在前面的成本分析中,之所以没有把 FaaS 之外的成本包含在内,是因为基于 Serverful 的架构,也可能需要使用到这些产品

Serverelss 应用的成本

  • FaaS
  • 事件源的成本和相关服务成本

如何控制成本

成本预测

成本预测主要就是根据以往的数据预测未来的成本

bash
月末费用 = 当前费用 * (每月/今天的天数)
成本监控

就像我们使用监控来观测程序是否正常运行一样,Serverless 应用的成本监控也非常重要

由于函数被恶意攻击最终产生了大量费用,直到月底收到账单通知才发现

  • 可以基于 Serverless 开发一个简单的成本监控程序
  • 也可以使用一些第三方的成本分析和成本监控平台

成本优化总结

Serverless 应用的 成本

  • 分析
  • 优化
  • 控制

基于 Serverless 架构,不用再为闲置的服务器付费,只为实际使用的资源付费就可以了;

同时还可以通过提高 Serverelss 应用的性能,进一步优化成本;

  • Serverless 应用的成本包括 FaaS 中函数执行的成本以及函数所依赖的触发器、数据源和 BaaS 服务的成本
  • Serverless 中函数按照执行次数和执行时间进行收费因此能大幅降低成本
  • 可以通过提升 Serverless 函数的性能来优化成本

5.系统迁移:传统项目如何迁移到 Serverless

前言

Serverless 有很多优点可以让你不用关心运维、按量付费节省成本...

Serverless 是一项新的技术,和传统开发方式区别很大,迁移成本也很大

基于 Serverless 应用是由 FaaS 和 BaaS 组成,传统应用要想迁移到 Serverless 架构上,就要进行相关的改造

这一节,带你了解怎么把传统 Web 服务进行 Serverless 改造,知道自己的应用适不适合迁移到 Serverless 架构、具体怎么实现以及迁移过程中有哪些需要注意的地方

传统应用应该如何迁移到 Serverless

应用进程是持续运行在服务器上的

应用进程是持续运行在服务器上的

  • 同一个服务器上的内存可以共享,所以传统应用通常可以在内存中缓存数据,以便提升计算性能
  • 基于 Serverless 架构的应用,内存缓存通常没有意义传统应用迁移到 Serverless 架构面临的第一个改造点就是内存缓存问题

1.在 Serverless 架构的应用中一般用缓存数据库做缓存

在传统应用中(尤其分布式应用),大部分时候我们也会使用缓存数据库因为服务器和服务器之间,也无法共享内存,所以内存缓存也仅作用于当前服务器处理的所有请求

用缓存数据库做缓存

2.缓存数据带来的第二个改造点,就是身份认证

身份认证是传统应用迁移到 Serverless 的第二个改造点

1.基于 cookie-session 的认证方式通常是把身份信息保存在服务端的 session 中

  • 现在大部分 cookie-session 的身份认证会将 session 存储在缓存数据库,这样就降低了迁移成本

    2.一些传统应用可能还会对磁盘有很多读写操作

  • 部署传统应用的磁盘是直接挂载到服务器上的所以就算应用重启了,服务器和磁盘也依旧存在

Serverless 函数运行在 FaaS 平台上

函数运行时只会有一个临时目录的读写权限,一旦运行环境被释放,该临时目录也会被释放,所以磁盘数据无法持续存储

对于有读写磁盘需求的应用,应该如何迁移到 Serverless 架构呢?

  • 可以为 Serverless 函数挂载一个持久存储只要不释放数据可以永久保存
  • 不同函数可以共用同一个持久化存储这样不同函数就可以读写同一份数据
  • 计算和存储分离了,这样更利于应用扩缩容

传统应用读取磁盘数据

传统应用读取磁盘数据

Serverless 应用使用持久化存储读写数据

![Serverless 应用使用持久化存储读写数据](.\img\Serverless 应用使用持久化存储读写数据.jpg)

3.使用 API 网关做统一接入是架构上的改造,应用代码也需要改造

传统应用统一接入

传统应用统一接入

Serverless 应用基于 API 网关实现统一接入

![Serverless 应用基于API 网关实现统一接入](.\img\Serverless 应用基于 API 网关实现统一接入.jpg)

将传统 Web 服务 Serverless 化是传统应用迁移到 Serverless 架构的又一个改造点

Web 服务 Serverless 化

将 Web 服务 Serverless 化的核心工作就是开发一个适配层,通过适配层将函数的事件对象转化为标准的 Web 请求

流程图示例

![事件对象转化为标准的 Web 请求](.\img\事件对象转化为标准的 Web 请求.jpg)

传统 Web 框架 Serverless 化比较麻烦的地方就在于:你需要完全理解 Web 框架 和 Serverless 函数事件的每个参数

所以各个云厂商为方便用户开发,也提供了依赖包

  • 阿里云函数计算提供的:@webserverless/fc-express
  • 腾讯云云函数提供的:tencent-serverless-http

步骤:

  • 创建一个自定义 HTTP Server
  • 将事件对象转换为 HTTP 请求参数,并转发到自定义的 HTTP Server
  • 将 HTTP 响应转换为函数返回值

![Web 服务 Serverless 化步骤图例](.\img\Web 服务 Serverless 化步骤图例.jpg)

自定义运行时服务化

前面自定义运行原理时那一节

学习了如何实现一个自定义运行时,其中自定义运行时的原理:本质上也是在函数中实现一个 HTTP 服务

传统 Web 服务 Serverless 化的原理与自定义运行时的原理是非常类似的,因此基于自定义运行时,可以轻松的将传统 web 服务 Serverless 化,这样就不用开发适配层

自定义运行时,有两种方式

  • 1.在函数中直接创建 HTTP 服务
  • 2.通过 Docker 镜像启动一个 HTTP 服务

传统 Web 服务 Serverless 化总结

  • 1.通过适配层,由适配层将事件对象转换为标准 Web 请求
  • 2.通过自定义运行时,在函数中创建一个 HTTP 服务该 HTTP 服务将函数事件处理后转发给传统 Web 服务
  • 3.通过自定义运行时,将传统 Web 服务构建为自定义镜像

这一节学习了怎么把传统应用迁移到 Serverless

  • 传统应用迁移到 Serverless,想要考虑内存缓存、身份认证、持久化存储、Web 服务 Serverless 化等改造点
  • 如果一个应用本身就是分布式部署的,且在架构上是计算和存储分离的,则比较容易迁移到 Serverless
  • Web 服务 Serverless 化主要原理是实现一个自定义 HTTP 服务,通过该 HTTP 服务处理事件对象和 Web 请求的差异
  • 通过实现适配层和自定义运行时等方案实现 Web 服务 Serverless 化

作业:开发一个简单的 Express.js 应用,将其部署到 Serverless 平台上

Released under the MIT License.