前言

首先介绍下在本文出现的几个比较重要的概念:

函数计算(Function Compute): 函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传。函数计算准备计算资源,并以弹性伸缩的方式运行用户代码,而用户只需根据实际代码运行所消耗的资源进行付费。函数计算更多信息 参考。

Fun: Fun 是一个用于支持 Serverless 应用部署的工具,能帮助您便捷地管理函数计算、API 网关、日志服务等资源。它通过一个资源配置文件(template.yml),协助您进行开发、构建、部署操作。Fun 的更多文档 参考。

2.0 版本的 Fun,在部署这一块做了很多努力,并提供了比较完善的功能,能够做到将云资源方便、平滑地部署到云端。但该版本,在本地开发上的体验,还有较多的工作要做。于是,我们决定推出 Fun Local 弥补这一处短板。

Fun Local: Fun Local 作为 Fun 的一个子命令存在,只要 Fun 的版本大于等于 2.6.0,即可以直接通过 fun local 命令使用。Fun Local 工具可以将函数计算中的函数在本地完全模拟运行,并提供单步调试的功能,旨在弥补函数计算相对于传统应用开发体验上的短板,并为用户提供一种解决函数计算问题排查的新途径。

《开发函数计算的正确姿势》系列除本篇是为用户介绍 fun local 的使用方法外,其他几篇都会向用户展示 Fun Local 对于函数计算开发所带来的效率上的巨大提升。

Fun Local 命令格式

使用 fun local invoke -h 可以查看 fun local invoke 的帮助信息:

$ fun local invoke -h
Usage: invoke [options] <[service/]function> Run your serverless application locally for quick development & testing. Options: -d, --debug-port <port> used for local debugging
-c, --config <ide> print out ide debug configuration. Options are VSCode
-e, --event <path> event file containing event data passed to the function
-h, --help output usage information

本地运行函数

运行函数的命令格式为:

fun local invoke [options] <[service/]function>

其中 options、service 都是可以省略的。
从调用方式上,可以理解为,fun local invoke 支持通过 函数名 调用,或者 服务名/函数名 的方式调用,即

fun local invoke function
fun local invoke service/function

比如,如果要运行名为 php72 的函数,可以直接通过以下命令完成:

fun local invoke php72

调用结果为:

再比如,要运行名为 nodejs8 的函数,可以使用:

fun local invoke nodejs8

会得到如下结果:

如果 template.yml 中包含多个服务,而多个服务中包含相同名称的函数时,通过函数名的方式调用 fun 只会运行第一个名称匹配的函数。

如果想要精准匹配,可以使用 服务名/函数名 的方式。

比如想要调用 localdemo 下的 php72,可以使用:

fun local invoke localdemo/php72

在本例中,会得到和 fun local invoke php72 一致的结果。

以下是一个运行 nodejs8 函数的演示:

本地运行 java 类型的函数

java 不同于解释型的语言,在作为函数运行前,需要先编译。在我们的例子中,可以进入到 demo 中的 java8 目录,然后执行:

mvn package

可以看到 log:

[INFO] skip non existing resourceDirectory /Users/tan/code/fun/examples/local/java8/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ demo ---
[INFO] No sources to compile
[INFO]
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ demo ---
[INFO] No tests to run.
[INFO]
[INFO] --- maven-dependency-plugin:2.8:copy-dependencies (copy-dependencies) @ demo ---
[INFO] fc-java-core-1.0.0.jar already exists in destination.
[INFO]
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ demo ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.223 s
[INFO] Finished at: 2018-11-22T10:45:14+08:00
[INFO] Final Memory: 15M/309M
[INFO] ------------------------------------------------------------------------

该命令会在 java8/target 目录下生成 demo-1.0-SNAPSHOT.jar 文件。

由于我们在 template.yml 中配置的 CodeUri 为 java8/target/demo-1.0-SNAPSHOT.jar,因此不需要任何改动,可以直接通过以下命令运行:

fun local invoke java8

运行结果如下:

以下是一个运行 java8 函数的演示:

本地调试

fun local invoke 支持 -d, --debug-port <port> 选项,可以对函数进行本地单步调试。本文档只介绍如何配置调试,并不涉及调试技巧,更多文章,请参考。

备注:Fun Local 涉及到的 debugging 技术全部都基于各个语言通用的调试协议实现的,因此无论什么语言的开发者,即使不喜欢用 VSCode,只要使用对应语言的 remote debugging 方法都可以进行调试。

本地调试 nodejs、python 类型的函数

对于 nodejs6、nodejs8、python2.7、python3、java8 类型的函数,调试方法基本一致。下面拿 nodejs8 举例。

我们上面演示了可以通过 fun local invoke nodejs8 来运行名称为 nodejs8 的函数,如果想对该函数进行调试,只需要使用 -d 参数,并配置相应的端口号即可。

比如我们以调试方式运行函数,并将调试端口设定在 3000,可以通过下面的命令:

fun local invoke -d 3000 nodejs8

另外,推荐添加 --config 参数,在调试的同时,可以输出用来调试的 IDE 的配置信息:

fun local invoke -d 3000 --config VSCode nodejs8

命令执行结果如下:

skip pulling images ...
you can paste these config to .vscode/launch.json, and then attach to your running function
///////////////// config begin /////////////////
{
"version": "0.2.0",
"configurations": [
{
"name": "fc/localdemo/nodejs8",
"type": "node",
"request": "attach",
"address": "localhost",
"port": 3000,
"localRoot": "/Users/tan/code/fun/examples/local/nodejs8",
"remoteRoot": "/code",
"protocol": "inspect",
"stopOnEntry": false
}
]
}
///////////////// config end /////////////////
Debugger listening on ws://0.0.0.0:3000/b65c288b-bd6a-4791-849b-b03e0d16b0ce
For help see https://nodejs.org/en/docs/inspector

程序会阻塞在这里,并不会继续往下执行。只有 IDE 的连接上来后,程序才会继续执行。接下来,我们针对 VSCode 配置、VSCode 调试两个方面分别进行讲解。

其中 VSCode 配置只有在第一次对函数进行调试时才需要,如果已经配置过,则不需要再次配置。

VSCode 配置

  1. 创建 vscode launch.json 文件
  2. 复制日志中的 config begin 与 config end 之间的配置到 launch.json 中。
  3. 完成上面配置后,在 Debug 视图可以看到配置的函数列表。

至此,VSCode 配置完成。VSCode 更多配置知识可以参考官方文档。

VSCode 调试

VSCode 配置成功后,只需要在 VSCode 编辑器侧边栏单击设置断点,然后点击“开始调试”按钮,即可开始调试。

以下是一个 nodejs8 函数本地单步调试的流程例子:

本地调试 java 类型的函数

调试 java 函数的过程和 nodejs、python 是类似的。但由于 java 程序员通常喜欢用 IDEA、Eclipse 这样的 IDE,所以我们单独拿出来说一下。

使用 VSCode 调试 java

使用 VSCode 调试 java 时,需要安装两个插件:Language Support for Java(TM) by Red HatDebugger for Java。利用 VSCode 的插件市场安装插件很简单,可以 参考。

以下是一个使用 VSCode 调试 java 类型函数的例子:

使用 IDEA 调试 java

IDEA 配置

IDEA 配置 remote debugging 还是比较简单的,首先在菜单栏依次点击 Run -> Edit Configurations...

然后新建一个 Remote Debugging:

然后我们随意输出一个名字,并配置端口号为 3000.

以下是一个配置 IDEA remote debugging 的完整流程演示:

使用 IDEA 开始调试

首先将 java 函数以 debug 的方式运行起来:

fun local invoke -d 3000 java8

可以看到函数卡在这里了,接着我们使用 IDEA 连接并开始调试。可以通过菜单栏上的 Run -> Debug... 或者工具栏直接点击 Debug 按钮,即可开始调试。

以下是一个用 IDEA 进行 remote debugging 的完整流程演示:

本地调试 php 类型的函数

php 的调试与其他类型的函数调试在流程上有一些不同。

首先,php 的运行通过 fun local invoke php72 命令完成,这与其他类型的函数一致。调试时,也像其他类型的函数一样,通过 -d 参数以调试模式启动函数:

fun local invoke -d 3000 --config VSCode php72

但不同的是,以 debug 方式运行 php 函数后,php 函数并没有阻塞等待 vscode 调试器的连接,而是直接运行结束。

skip pulling images ...
you can paste these config to .vscode/launch.json, and then attach to your running function
///////////////// config begin /////////////////
{
"version": "0.2.0",
"configurations": [
{
"name": "fc/localdemo/php72",
"type": "php",
"request": "launch",
"port": 3000,
"stopOnEntry": false,
"pathMappings": {
"/code": "/Users/tan/code/fun/examples/local/php7.2"
},
"ignore": [
"/var/fc/runtime/**"
]
}
]
}
///////////////// config end /////////////////
FunctionCompute php7.2 runtime inited.
FC Invoke Start RequestId: 6e8f7ed7-653d-4a6a-94cc-1ef0d028e4b4
FC Invoke End RequestId: 6e8f7ed7-653d-4a6a-94cc-1ef0d028e4b4
hello world RequestId: 6e8f7ed7-653d-4a6a-94cc-1ef0d028e4b4 Billed Duration: 48 ms Memory Size: 1998 MB Max Memory Used: 58 MB

这是因为,对于 php 程序,需要首先启动 vscode 的调试器。

php 类型的函数启动 VSCode 调试器的流程与其他类型的函数一致:复制上面日志中的 vscode 配置到 launch.json,单击“开始调试”即可。

然后在终端重新以调试模式启动 php 函数即可开始调试:

fun local invoke -d 3000 php72

Event 事件源

函数计算提供了丰富的触发器,包括但不局限于对象存储触发器、日志服务触发器、CDN 事件触发器等。在本地无论是运行还是调试函数时,为了能够完全模拟线上环境,通常需要构造触发事件。

触发事件可以是一段可读的 json 配置,也可以是一段非可读的二进制数据。这里我们拿 json 举例,假设触发事件内容为:

{
"testKey": "testValue"
}

想要将这段事件内容传给函数,可以通过以下三种途径:

  1. 管道: echo '{"testKey": "testValue"}' | fun local invoke nodejs8
  2. 文件: 将的 json 内容写入到文件,文件名随意,比如 event.json。然后通过 -e 指定文件名:fun local invoke -e event.json nodejs8 
  3. 重定向: fun local invoke nodejs8 < event.json 或者 fun local invoke nodejs8 <<< '{"testKey": "testValue"}' 等等。更多信息可以参考这篇文章。

环境变量

在 template.yml 中配置的 EnvironmentVariables 会与线上行为一致,当函数运行时,可以通过代码获取到。更多信息参考。

在本地运行函数时,除了 EnvironmentVariables 配置的环境变量,fun 还会额外提供一个 local=true 的环境变量,用来标识这是一个本地运行的函数。

通过这个环境变量,用户可以区分是本地运行还是线上运行,以便于进行一些特定的逻辑处理。

Initializer

在 template.yml 中配置的 Initializer 属性会与线上行为一致,当函数运行时,会首先运行 Initializer 指定的方法。Initializer 更多信息 参考。

Credentials

用户可以通过 Credentials 中存储的 ak 信息访问阿里云的其他服务。Fun local 在本地运行函数时,会按照与 fun deploy 相同的 策略 寻找 ak 信息。

关于函数计算 Credentials 的描述,可以参考。

以下是一个根据本地、线上环境的不同,利用函数提供的 Credentials 配置 oss client 的例子:

local = bool(os.getenv('local', ""))
if (local):
print 'thank you for running function in local!!!!!!'
auth = oss2.Auth(creds.access_key_id,
creds.access_key_secret)
else:
auth = oss2.StsAuth(creds.access_key_id,
creds.access_key_secret,
creds.security_token)

附录

代码

本文讲解涉及到的 demo 代码,托管在 github 上。项目目录结构如下:

.
├── java8
│ ├── pom.xml
│ ├── src
│ │ └── main
│ │ └── java
│ │ └── example
│ │ └── App.java
│ └── target
│ └── demo-1.0-SNAPSHOT.jar
├── nodejs6
│   └── index.js
├── nodejs8
│   └── index.js
├── php7.2
│   └── index.php
├── python2.7
│   └── index.py
├── python3
│   └── index.py
└── template.yml

template.yml 定义了函数计算模型,其中定义了一个名为 localdemo 的服务,并在该服务下,定义了 6 个函数,名称分别是 nodejs6、nodejs8、php72、python27、python3、java8。它们对应的代码目录由 template 中的 CodeUri 定义,分别位于 nodejs6、nodejs8、php7.2、python2.7、python3、java8 目录。

原文链接
本文为云栖社区原创内容,未经允许不得转载。

开发函数计算的正确姿势 —— 使用 Fun Local 本地运行与调试的更多相关文章

  1. 开发函数计算的正确姿势 —— 使用 ROS 进行资源编排

    前言 首先介绍下在本文出现的几个比较重要的概念: 函数计算(Function Compute): 函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传.函数计算 ...

  2. 开发函数计算的正确姿势——OCR 服务

    作者 | 杜万(倚贤) 阿里云技术专家 简介 首先介绍下在本文出现的几个比较重要的概念: OCR(光学字符识别):光学字符识别(Optical Character Recognition, OCR)是 ...

  3. 函数计算工具链新成员 —— Fun Local 发布啦

    刚刚,我们发布了函数计算工具链的新成员,Fun Local.欢迎大家使用! 如果你还不了解 Fun 是什么,我们来简单解释下. Fun 是什么 Fun 是 have Fun with Serverle ...

  4. 使用webpack开发ES6程序的正确姿势

    1.cnpm install babel-loader babel-core babel-preset-es2015 -D 2.cnpm install babel-plugin-transform- ...

  5. 开发工具IDE从入门到爱不释手(三)运行与调试

    一.启动项目 右键运行 菜单运行 run窗口运行 启动参数 -D可覆盖,application.properties中的配置 如: 自动编译 二.调试项目 断点调试 蓝色背景的行,就是当前程序停住的行 ...

  6. Serverless 解惑——函数计算如何安装字体

    前言 首先介绍下在本文出现的几个比较重要的概念: 函数计算(Function Compute):函数计算是一个事件驱动的服务,通过函数计算,用户无需管理服务器等运行情况,只需编写代码并上传.函数计算准 ...

  7. Taro 多端开发的正确姿势:打造三端统一的网易严选(小程序、H5、React Native)

    笔者所在的趣店 FED 早在去年 10 月份就已全面使用 Taro 框架开发小程序(当时版本为 1.1.0-beta.4),至今也上线了 2 个微信小程序.2 个支付宝小程序. 之所以选用 Taro, ...

  8. SpringBoot 开发案例之参数传递的正确姿势

    前言 开发这么多年,肯定还有不少小伙伴搞不清各种类型的参数是如何传递的,很多同学都是拿来即用,复制粘贴一把撸,遇到问题还是一脸懵逼. 姿势 学习参数传递的正确姿势,先说怎么做,再说为什么,本质上还是复 ...

  9. 函数计算: 让小程序开发进入 Serverless 时代

    点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 吴天龙(木吴 ...

随机推荐

  1. GitLab在centos7上安装和使用

    git的优点 git是分布式的,svn不是 git分布式本地就可以用,可以随便保存各种历史痕迹,不用担心污染服务器,连不上服务器也能提交代码.查看log. GIT分支和SVN的分支不同 分支在SVN中 ...

  2. php获取微信基础接口凭证Access_token

    php获取微信基础接口凭证Access_token的具体代码,供大家参考,具体内容如下 access_token是公众号的全局唯一票据,公众号调用各接口时都需使用access_token.开发者需要进 ...

  3. myeclipse中配置自己安装的Tomcat

    myeclipse中配置自己安装的Tomcat 在myeclipse中配置好jdk,Tomcat之后,如果是web项目需要部署运行,但在部署时发现配置好的Tomcat没有显示,只显示了myeclips ...

  4. 十五、过滤器(Filter)

    过滤器(Filter) 过滤器概述 1 什么是过滤器 过滤器JavaWeb三大组件之一,它与Servlet很相似!不它过滤器是用来拦截请求的,而不是处理请求的. 当用户请求某个Servlet时,会先执 ...

  5. 小程序textarea完美填坑

    相信做微信小程序的码友们都被textarea这个原生组件坑过,什么placeholder位置错乱,穿透弹窗或遮罩层,ios上输入法弹起后换行输入内容遮挡,删除输入内容时内容被遮挡等等... 反正综上所 ...

  6. MySQL表添加自增列

    mysql> create table zc_test2(id int); Query OK, rows affected (1.37 sec) mysql),(),(),(),(); Quer ...

  7. APP测试工具与技术

    AndroidDevTools Android Dev Tools官网地址:www.androiddevtools.cn 收集整理Android开发所需的Android SDK.开发中用到的工具.An ...

  8. limit实现的分页查询

    背景:原先是一次性查询加载到前段,表格插件自动分页,最近查询的数据量越来越大,长的时候需要等好几十秒,决定自己写一个后端分页,我写的和网上大神的略有不同,不是后端写一个类封装分页的参数,每次查询都是穿 ...

  9. #Java学习之路——基础阶段(第十篇)

    我的学习阶段是跟着CZBK黑马的双源课程,学习目标以及博客是为了审查自己的学习情况,毕竟看一遍,敲一遍,和自己归纳总结一遍有着很大的区别,在此期间我会参杂Java疯狂讲义(第四版)里面的内容. 前言: ...

  10. Web前端-JavaScript基础教程上

    Web前端-JavaScript基础教程 将放入菜单栏中,便于阅读! JavaScript是web前端开发的编程语言,大多数网站都使用到了JavaScript,所以我们要进行学习,JavaScript ...