关于serverless:Serverless-工程实践-Serverless-应用优化与调试秘诀

98次阅读

共计 5510 个字符,预计需要花费 14 分钟才能阅读完成。

作者|刘宇

前言:本文将以阿里云函数计算为例,提供了在线调试、本地调试等多种利用优化与调试计划。

Serverless 利用调试秘诀

在利用开发过程中,或者利用开发实现,所执行后果不合乎预期时,咱们要进行肯定的调试工作。然而在 Serverless 架构下,调试往往会受到极大的环境限度,呈现所开发的利用在本地能够衰弱、合乎预期的运行,然而在 FaaS 平台上产生一些不可预测的问题的状况。而且在一些非凡环境下,本地没有方法模仿线上环境,难以进行我的项目的开发和调试。

Serverless 利用的调试始终都是备受诟病的,然而各个云厂商并没有因而放弃在调试方向的深刻摸索。以阿里云函数计算为例,其提供了在线调试、本地调试等多种调试计划。

在线调试

1. 简略调试

所谓的简略调试,就是在控制台进行调试。以阿里云函数计算为例,其能够在控制台通过“执行”按钮,进行根本的调试,如图所示。


函数在线简略调试页面

必要的时候,咱们也能够通过设置 Event 来模仿一些事件,如图所示。


通过设置 Event 模仿事件

在线调试的益处是,能够应用线上的一些环境进行代码的测试。当线上环境领有 VPC 等资源时,在本地环境是很难进行调试的,例如数据库须要通过 VPC 拜访,或者有对象存储触发器的业务逻辑等。

2. 断点调试

除了简略的调试之外,局部云厂商也反对断点调试,例如阿里云函数计算的近程调试、腾讯云云函数的近程调试等。以阿里云函数计算近程调试为例,其能够通过控制台进行函数的在线调试。当创立好函数之后,用户能够抉择近程调试,并点击“开启调试”按钮,如图所示。


函数在线断点调试页面(一)

开启调试之后,稍等片刻,零碎将会进入近程调试界面,如图所示。


函数在线断点调试页面(二)

此时能够进行一些断点调试,如图所示。


函数在线断点调试页面(三)

本地调试

1. 命令行工具

就目前来看,大部分 FaaS 平台都会为用户提供绝对齐备的命令行工具,包含 AWS 的 SAM CLI、阿里云的 Funcraft,同时也有一些开源我的项目例如 Serverless Framework、Serverless Devs 等对多云厂商的反对。通过命令行工具进行代码调试的办法很简略。以 Serverless Devs 为例,本地调试阿里云函数计算。

首先确保本地领有一个函数计算的我的项目,如图所示。


本地函数计算我的项目

而后在我的项目下执行调试指令,例如在 Docker 中进行调试,如图所示。


命令行工具调试函数计算

2. 编辑器插件

以 VScode 插件为例,当下载好阿里云函数计算的 VSCode 插件,并且配置好账号信息之后,能够在本地新建函数,并且在打点之后能够进行断点调试,如图所示。


VSCode 插件调试函数计算

当函数调试实现之后,执行部署等操作。

其余调试计划

1.Web 框架的本地调试

在阿里云 FaaS 平台开发传统 Web 框架,以 Python 语言编写的 Bottle 框架为例,能够减少以下代码:

app = bottle.default_app()
并且对 run 办法进行条件限度 (if __name__ == '__main__'):if __name__ == '__main__':
    bottle.run(host='localhost', port=8080, debug=True)
例如:# index.py
import bottle

@bottle.route('/hello/<name>')
def index(name):
    return "Hello world"

app = bottle.default_app()

if __name__ == '__main__':
    bottle.run(host='localhost', port=8080, debug=True)

当部署利用到线上时,只须要在入口办法处填写 ndex.app,即可实现平滑部署。

2. 本地模仿事件调试

针对非 Web 框架,咱们能够在本地构建一个办法,例如要调试对象存储触发器:

import json
def handler(event, context):
    print(event)
def test():
    event = {
        "events": [
            {
                "eventName": "ObjectCreated:PutObject",
                "eventSource": "acs:oss",
                "eventTime": "2017-04-21T12:46:37.000Z",
                "eventVersion": "1.0",
                "oss": {
                    "bucket": {
                        "arn": "acs:oss:cn-shanghai:123456789:bucketname",
                        "name": "testbucket",
                        "ownerIdentity": "123456789",
                        "virtualBucket": ""},"object": {"deltaSize": 122539,"eTag":"688A7BF4F233DC9C88A80BF985AB7329","key":"image/a.jpg","size": 122539},
                    "ossSchemaVersion": "1.0",
                    "ruleId": "9adac8e253828f4f7c0466d941fa3db81161****"
                },
                "region": "cn-shanghai",
                "requestParameters": {"sourceIPAddress": "140.205.***.***"},
                "responseElements": {"requestId": "58F9FF2D3DF792092E12044C"},
                "userIdentity": {"principalId": "123456789"}
            }
        ]
    }
    handler(json.dumps(event), None)
if __name__ == "__main__":
    print(test())

这样,通过结构一个 event 对象,即可实现模仿事件触发。

Serverless 利用优化

资源评估仍旧重要

Serverless 架构尽管是按量付费的,然而并不代表它就肯定比传统的服务器租用费用低。如果对本人的我的项目评估不精确,对一些指标设置不合理,Serverless 架构所产生的费用可能是微小的。

个别状况下,FaaS 平台的免费和三个指标有间接关系,即所配置的函数规格(例如内存规格等)、程序所耗费的工夫以及产生的流量费用。通常状况下,程序所耗费的工夫可能与内存规格、程序自身所解决的业务逻辑无关。流量费用与程序自身和客户端交互的数据包大小无关。所以在这三个常见的指标中,可能因为配置不标准导致计费呈现比拟大偏差的就是内存规格。以阿里云函数计算为例,假如有一个 Hello World 程序,每天都会被执行 10000 次,不同规格的内存所产生的费用(不包含网络费用)如表所示。

通过表中能够看到,当程序在 128MB 规格的内存中能够失常执行,如果谬误地将内存规格设置成 3072MB,可能每月产生的费用将会暴涨 25 倍!所以在上线 Serverless 利用之前,要对资源进行评估,以便以更正当的配置来进一步降低成本。

正当的代码包规格

各个云厂商的 FaaS 平台中都对代码包大小有着限度。抛掉云厂商对代码包的限度,单纯地说代码包的规格可能会产生的影响,通过函数的冷启动流程能够看到,如图所示。


函数冷启动流程简图

在函数冷启动过程中,当所上传的代码包过大,或者文件过多导致解压速度过慢,就会使加载代码过程变长,进一步导致冷启动工夫变久。

构想一下,当有两个压缩包,一个是只有 100KB 的代码压缩包,另一个是 200MB 的代码压缩包,两者同时在千兆的内网带宽下理想化(即不思考磁盘的存储速度等)下载,即便最大速度能够达到 125MB/s,那么前者的下载工夫只有不到 0.01 秒,后者须要 1.6 秒。除了下载工夫之外,加上文件的解压工夫,那么两者的冷启动工夫可能就相差 2 秒。个别状况下,对于传统的 Web 接口,如果要 2 秒以上的响应工夫,实际上对很多业务来说是不能承受的,所以在打包代码时就要尽可能地升高压缩包大小。以 Node.js 我的项目为例,打包代码包时,咱们能够采纳 Webpack 等办法来压缩依赖包大小,进一步升高整体代码包的规格,晋升函数的冷启动效率。

正当复用实例

为了更好地解决冷启动的问题、更正当地利用资源,各个云厂商的 FaaS 平台中是存在实例复用状况的。所谓的实例复用,就是当一个实例实现一个申请后并不会开释,而是进入静默的状态。在肯定工夫范畴内,如果有新的申请被调配过去,则会间接调用对应的办法,而不须要再初始化各类资源等,这在很大水平上缩小了函数冷启动的状况呈现。为了验证,咱们能够创立两个函数:

 函数 1:# -*- coding: utf-8 -*-

def handler(event, context):
    print("Test")
    return 'hello world'
函数 2:# -*- coding: utf-8 -*-
print("Test")

def handler(event, context):
    return 'hello world'

在控制台点击“测试”按钮,对上述两个函数进行测试,判断其是否在日志中输入了“Test”,统计后果如表所示。


函数复用记录

能够看到,其实实例复用的状况是存在的。进一步思考,如果 print(“Test”) 语句是一个初始化数据库连贯,或者是函数 1 和函数 2 加载了一个深度学习模型,是不是函数 1 就是每次申请都会执行,而函数 2 能够复用已有对象?

所以在理论的我的项目中,有一些初始化操作是能够依照函数 2 实现的,例如:
 

  • 在机器学习场景下,在初始化的时候加载模型,防止每次函数被触发都会加载模型。
  • 在初始化的时候建设链接对象,防止每次申请都创立链接对象。
  • 其余一些须要首次加载时下载、加载的文件在初始化时实现,进步实例复用效率。

长于利用函数个性

各个云厂商的 FaaS 平台都有一些个性。所谓的平台个性,是指这些性能可能并不是 CNCF WG-Serverless Whitepaper v1.0 中规定的能力或者形容的能力,仅仅是作为云平台依据本身业务倒退和诉求从用户角度登程开掘进去并且实现的性能,可能只是某个云平台或者某几个云平台所领有的性能。这类性能个别状况下如果利用切当会让业务性能有质的晋升。

1.Pre-freeze & Pre-stop

以阿里云函数计算为例,在平台倒退过程中,用户痛点(尤其是妨碍传统利用平滑迁徙至 Serverless 架构)如下。

  • 异步背景指标数据提早或失落:如果在申请期间没有发送胜利,则可能被提早至下一次申请,或者数据点被抛弃。
  • 同步发送指标减少延时:如果在每个申请完结后都调用相似 Flush 接口,不仅减少了每个申请的延时,对于后端服务也产生了不必要的压力。
  • 函数优雅下线:实例敞开时利用有清理连贯、敞开过程、上报状态等需要。在函数计算中实例下线时,开发者无奈把握,也短少 Webhook 告诉函数实例下线事件。

依据这些痛点,阿里云公布了运行时扩大(Runtime Extensions)性能。该性能在现有的 HTTP 服务编程模型上扩大,在已有的 HTTP 服务器模型中减少了 PreFreeze 和 PreStop Webhook。扩大开发者负责实现 HTTP handler,监听函数实例生命周期事件,如图所示。


扩大编程模型与现有编程模型解决的工作内容简图

  • PreFreeze:在每次函数计算服务决定冷冻以后函数实例前,函数计算服务会调用 HTTP GET/prefreeze 门路,扩大开发者负责实现相应逻辑以确保实现实例冷冻前的必要操作,例如期待指标发送胜利等,如图所示。函数调用 InvokeFunction 的工夫不蕴含 PreFreeze Hook 的执行工夫。


PreFreeze 时序图

  • PreStop:在每次函数计算决定进行以后函数实例前,函数计算服务会调用 HTTP GET/prestop 门路,扩大开发者负责实现相应逻辑以确保实现实例开释前的必要操作,如期待数据库链接敞开,以及上报、更新状态等,如图所示。


PreStope 时序图

2. 单实例多并发

家喻户晓,各云厂商的函数计算通常是申请级别的隔离,即当客户端同时发动 3 个申请到函数计算,实践上会产生 3 个实例进行应答,这个时候可能会波及冷启动以及申请之间状态关联等问题。因而,局部云厂商提供了单实例多并发的能力(例如阿里云函数计算)。该能力容许用户为函数设置一个实例并发度(InstanceConcurrency),即单个函数实例能够同时解决多个申请,如图所示。


单实例多并发成果简图

如上图所示,假如同时有 3 个申请须要解决,当实例并发度设置为 1 时,函数计算须要创立 3 个实例来解决这 3 个申请,每个实例别离解决 1 个申请;当实例并发度设置为 10 时(即 1 个实例能够同时解决 10 个申请),函数计算只须要创立 1 个实例就能解决这 3 个申请。

单实例多并发的劣势如下。

  • 缩小执行时长,节俭费用。例如,偏 I/O 函数能够在一个实例内并发解决申请,缩小了实例数,从而缩小总的执行时长。
  • 申请之间能够共享状态。多个申请能够在一个实例内共用数据库连接池,从而缩小和数据库之间的连接数。
  • 升高冷启动概率。因为多个申请能够在一个实例内解决,创立新实例的次数会缩小,冷启动概率升高。

单实例多并发的利用场景比拟宽泛,例如函数中有较多工夫在期待上游服务响应的场景就比拟适宜应用该性能。单实例多并发也有不适宜利用的场景,例如函数中有共享状态且不能并发拜访时,单个申请的执行要耗费大量 CPU 及内存资源,这时就不适宜应用单实例多并发性能。

* 对于作者:
刘宇(江昱)国防科技大学电子信息业余在读博士,阿里云 Serverless 产品经理,阿里云 Serverless 云布道师,CIO 学院特聘讲师。*

正文完
 0