Local 命令

local 命令是在本地对函数调试的命令。

⚠️ 注意:该命令对 Docker 有所依赖,所以在使用该命令时,需要先进行 Docker 安装

命令解析

当执行命令local -h/local --help时,可以获取帮助文档。

在该命令中,包括了两个个子命令:

local invoke 命令

local invoke 命令,是进行本地事件函数调试的命令。

💡 事件函数指的是非 HTTP 触发器的函数,包括不限于 OSS 触发器函数、CDN 触发器函数、Tablestore 触发器函数等。

当执行命令local invoke -h/local invoke --help时,可以获取帮助文档。

参数解析

参数全称参数缩写Yaml 模式下必填参数含义
evente选填传入 event 函数的 event 事件数据,可以通过 s cli fc-event 指令快速获取事件数据示例,详细操作参考这里
event-filef选填以文件形式传入 event 事件数据
event-stdins选填以标准输入形式传入 event 事件数据
modem选填调试模式选择,包括:
- normal: 默认模式,本地函数运行容器在函数执行完成后立刻退出
server: 本地函数运行容器一直存在,用户在其他终端发起的本地调用会复用该容器
api: 支持通过 sdk 调用本地函数
configc选填指定断点调试时使用的 IDE,取值范围:vscode, pycharm, intellij
debug-portd选填指定断点调试端口
debug-args-选填断点调试时传入的参数, 详情见附录中的默认断点调试参数
debugger-pathq选填自定义断点调试器路径,会将本地指定路径挂载到程序运行环境的 /tmp/debugger_file 之中
tmp-dir-选填自定义函数运行环境中 /tmp 路径的本机挂载路径,默认为 ./.s/tmp/invoke/serviceName/functionName/
server-port-选填自定义本地监听 server 的端口,默认是在 7000 到 8000 间的随机端口
sdk-version-选填选填

当前命令还支持部分全局参数(例如-a/--access, --debug, --help等),详情可参考 Serverless Devs 全局参数文档

操作案例

有资源描述文件(Yaml)时,可以直接执行s local invoke 进行本地调试,完成的输出示例:

FC Invoke Start RequestId: 0ba8ac3f-abf8-46d4-b61f-8e0f9f265d6a
2021-11-11T05:45:58.027Z 0ba8ac3f-abf8-46d4-b61f-8e0f9f265d6a [INFO] hello world
FC Invoke End RequestId: 0ba8ac3f-abf8-46d4-b61f-8e0f9f265d6a
hello world

RequestId: 0ba8ac3f-abf8-46d4-b61f-8e0f9f265d6a      Billed Duration: 146 ms     Memory Size: 128 MB     Max Memory Used: 23 MB

local start 命令

local start 命令,是进行本地 HTTP 函数调试的命令。

当执行命令local start -h/local start --help时,可以获取帮助文档。

参数解析

参数全称参数缩写Yaml 模式下必填参数含义
configc选填指定断点调试时使用的 IDE,可选:vscode, pycharm, intellij
debug-portd选填指定断点调试端口
custom-domain-选填以自定义域名作为 HTTP Server 的访问 url
debug-args-选填断点调试时传入的参数,详情见附录中的默认断点调试参数
debugger-path-选填自定义断点调试器路径,会将本地指定路径挂载到程序运行环境的 /tmp/debugger_file 之中
tmp-dir-选填自定义函数运行环境中 /tmp 路径的本机挂载路径,默认为 ./.s/tmp/invoke/serviceName/functionName/
server-port-选填自定义本地监听 HTTP Server 的端口,默认是在 7000 到 8000 间的随机端口

当前命令还支持部分全局参数(例如-a/--access, --debug, --help等),详情可参考 Serverless Devs 全局参数文档

操作案例

有资源描述文件(Yaml)时,可以直接执行s local start 进行资源部署,部署完成的输出示例:

    url: http://localhost:7665/2016-08-15/proxy/fc-deploy-service/http-trigger-py36/
    methods: GET
    authType: anonymous

    Tips for more action:
        Start with customDomain method: [s local start auto]
        Debug with customDomain method: [s local start -d 3000 auto]

此时,可以根据命令行提示的url信息,在浏览器中查看 HTTP 函数本地调试的具体内容。

如果需要通过自定义域名的方式调试 HTTP 函数,则可以在调试时增加--custom参数,输出示例:

  url: http://localhost:7308/
    methods: GET
    authType: anonymous

关于自定义域名调试模式以及默认的调试模式区别:在使用函数计算的 HTTP 函数时,是有两个域名组成:

  • 系统域名地址,例如http://localhost:7665/2016-08-15/proxy/fc-deploy-service/http-trigger-py36/
  • 自定义域名地址,例如http://abc.com/

这两个地址在非 custom runtime 函数中是没有区别的,而对于 custom-runtime/custom-container 函数,这两个地址的核心区别是其path不同,例如以传统的 Web 框架为例:

  • 系统域名地址的基础路径匹配是:/2016-08-15/proxy/fc-deploy-service/http-trigger-py36/
  • 自定义域名地址的基础路径匹配可以是任何形式,包括/

由于路径的不同,所以在代码开发和处理的时候,都会有所不同,如果使用某个 Web 框架(例如 Express、Django 等),匹配的首页地址为/,那么使用系统域名地址则可能会出现404,这个时候较为推荐使用自定义域名,获得更原生的体验。所以为了满足开发者在系统域名与自定义域名不同模式下的调试需要,本组件支持--custom-domain参数进行自定义域名模式调试。 如果既要使用 custom-runtime/custom-container 函数,又要使用系统域名,还要不处理系统基础路径,那么可以在发给函数的 HTTP 请求中增加 header: x-fc-invocation-target: 2016-08-15/proxy/$ServiceName/$functionName 即可

注意事项

针对 s local start 本地调用交互设计:

  • 如果不存在 customDomains 配置,一定使用系统域名路径:/2016-08-15/proxy/serviceName/functionName/
  • 存在 customDomains 配置
    1. 指定 --custom-domain 参数, 使用指定域名配置的路径
    2. 未指定 --custom-domain 2.1 如果 customDomains 仅有一个,直接使用此域名配置的路径 2.2 如果存在多个则产生交互,选择配置的域名路径

      如果使用系统域名路径,使用 --custom-domain system 或者选择时候选择 system

调用时模拟 NAS 目录

当 yaml 中配置了 nasConfig 时,local 可以模拟 nas 的目录结构,例如:

s.yaml 配置如下

services:
  helloworld:
    component: fc
    props:
      region: cn-hangzhou
      service:
        name: hello-world-service
        description: 'hello world by serverless devs'
        vpcConfig: auto
        nasConfig:
          userId: 10003
          groupId: 10003
          mountPoints:
            - serverAddr: xxx.cn-hangzhou.nas.aliyuncs.com
              nasDir: /hello-world-service
              fcDir: /mnt/auto
      function:
        name: event-py3
        description: 'hello world by serverless devs'
        runtime: python3
        codeUri: ./code
        handler: index.handler
        memorySize: 128
        timeout: 60

code/index.py 内容如下

# coding=utf-8
import logging
import os

def handler(event, context):
  logger = logging.getLogger()
  logger.info('============')
  os.system("ls /mnt/auto")
  logger.info('============')
  return 'hello world\n'

s.yaml 同目录级别 .s/nas/auto-default/hello-world-service 的目录下存在一个文件为 test.ts 的文件,目录结构及执行结果如下:

断点调试

VSCode

使用 VSCode 进行断点调试时,流程十分简单。

调试 Event 函数

step1:打开终端,进入目标项目下,输入启动指令
$ s local invoke --config vscode --debug-port 3000

启动指令执行后,本地的函数计算执行容器会有一定阻塞,我们需要等待调用;与此同时当前项目会自动生成 .vscode/launch.json 文件,该文件是基于 VSCode 进行调试的配置文件,若该文件已经存在,那么启动指令会打印相应配置文本,如下图所示,需要利用这部分内容覆盖已有 .vscode/launch.json 中的内容。

step2:启动断点调试器

打开 VSCode 界面,然后打开 s.yml 中 codeUri 所存放的源代码,为其打上断点,接着点击开始调试按钮,具体执行如下图所示。

启动调试器后,程序便已经启动,此时就可以开始进行我们的断点调试工作了。

断点调试实操视频
  • Event 函数

    Watch the video

  • php7.2 event 函数 php7.2 runtime 的本地调试 IDE 建议使用 VSCode,其断点调试步骤与其他语言有一定差异性,因此单独进行介绍

    Watch the video

调试 HTTP 函数

step1:打开终端,进入目标项目下,输入启动指令
$ s local start --config vscode --debug-port 3000

启动指令执行后,本地的函数计算执行容器会阻塞等待调用,并打印访问 http 函数的 url 字段。

step2:启动断点调试器

打开 VSCode 界面,然后打开 s.yml 中 codeUri 存放的源代码,为其打上断点,接着点击开始调试按钮,如图所示。此时在启动指令终端页面,会出现 "Debugger attached." 字段,说明调试器启动成功,等待被调用。

step3:开始断点调试

可以通过 curl 指令、浏览器等方式访问 Http 函数的 URL,此时程序启动,断点调试开始。

step4:结束断点调试

调试完成后,主动关闭断点调试器,然后在启动指令终端页面,执行 Ctrl+C 即可退出调试进程。

断点调试实操视频
  • Http 函数

    Watch the video

  • php7.2 Http 函数

    Watch the video

Intellij

基于 Intellij 进行断点调试时,针对不同语言需要手动在 IDE 中配置相应地断点调试器,由于使用 Intellij 开发最多的语言是 Java,同时更换 IDE 后,唯一不同的步骤只有“启动断点调试器”,因此接下来我们将以本地调试 Java Event 函数为例,对“启动断点调试器”步骤进行详细说明。

step1:打开终端,进入目标项目下,输入启动指令

由于 Java 是编译型语言,因此在开始前需要对程序进行打包,本文示例会使用 mvn package 对函数打包

$ mvn package
$ s local invoke --config intellij --debug-port 3000
step2:启动断点调试器
  • 打开 Intellij 界面,在菜单栏依次选择 Run -> Edit Configurations, 随后如下图所示,新建一个 Remote JVM Debug

  • 接着,自定义调试器名称,并将端口设置为 3000,如下图所示。

  • 最后,打开 s.yml 中 codeUri 存放的源代码,为其打上断点,接着点击开始调试按钮,如图所示。

断点调试实操视频

Watch the video

Pycharm

Pycharm 支持的运行时有 python2.7 和 python3 两个版本。在 Pycharm 中进行断点调试时,不仅需要在 IDE 中配置断点调试器,还需要对使用者的源码进行侵入式修改,由于操作步骤内容与常规内容有所不同,接下来我们详解一下这部分的调试步骤。

step1:打开终端,进入目标项目下,输入启动指令
# event 函数
$ s local invoke --config pycharm --debug-port 3000

# http 函数
$ s local start --config pycharm --debug-port 3000

与之前不同的是,Event 函数启动指令执行完成后,并不会出现阻塞的情况,而是会直接执行成功。此时就需要记录 "Tips for PyCharm remote debug" 内容,具体内容示例如图所示,记录完成后,如果是 Http 函数,则输入 Ctrl+C 退出启动程序。

step2:启动断点调试器

启动断点调试器主要包含 IDE 断点调试器配置和源码更新两部分。

  • 打开 pycharm 界面,在菜单栏依次选择 Run -> Edit Configurations

  • 如图中所示,新建一个 Python Debug Server

  • 设置自定义调试器名称,并基于图五中获取的内容配置 IDE host name、Port 以及 Path mappings 这三个调试器配置的详情,如图中所示。

  • 打开 s.yml 中 codeUri 存放的源代码,将例图中(Tips for PyCharm remote debug 内容示例)的代码内容粘贴到代码开头,然后按需在源码指定位置打上断点,接着点击开始调试按钮,具体操作如图 (pycharm 启动断点调试器)所示。

step3:开始断点调试

打开终端,并进入目标项目,执行启动指令

此时可以不用带上断点调试的相关参数。

# event 函数
$ s local invoke

# http 函数
$ s local start
  • Event 函数启动指令执行后会直接进入断点调试阶段

  • Http 函数启动指令执行后,可以先通过 curl 指令、浏览器等方式访问 Http 函数的 URL,此时程序会启动,断点调试就开始了。

step4:结束断点调试

调试完成后,主动关闭断点调试器,对于 Http 函数而言,在启动指令终端页面,需执行 Ctrl+C 方可退出调试进程。

断点调试实操视频
  • Event 函数

    Watch the video

  • Http 函数

    Watch the video

附录

默认断点调试参数

RuntimeDefault Debug Args
nodejs 6--debug-brk=${debugPort}
nodejs 8/10/12/14--inspect-brk=0.0.0.0:${debugPort}
python 2.7/3/3.9-m ptvsd --host 0.0.0.0 --port ${debugPort} --wait
java 8-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,quiet=y,address=${debugPort}
java 11-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,quiet=y,address=*:${debugPort}
php7.2remote_enable=1 remote_autostart=1 remote_port=${debugPort} remote_host=${ip.address()}
在 GitHub 上编辑本页面 更新时间: Wed, Aug 10, 2022