- 最新动态
- 功能总览
- 产品介绍
- 计费说明
- 快速入门
- 用户指南
-
最佳实践
- FunctionGraph最佳实践汇总
- FunctionGraph性能优化实践
- FunctionGraph冷启动优化实践
- FunctionGraph安全最佳实践
- 使用函数处理DIS数据
- 函数+LTS:日志实时分析实战
- 函数+CTS:登录/登出安全分析实战
- 定时开关华为公有云虚拟机
- 使用SpringBoot构建FunctionGraph HTTP函数
- 创建使用自定义认证且后端为FunctionGraph的API
- 函数+APIG:处理文件上传
- 使用函数处理IOT数据
- 函数+DEW:加解密文件
- 工作流+函数:自动化处理OBS中数据
- 函数+LTS:日志实时过滤
- 通过应用中心部署AI绘画Stable-Diffusion
- 使用Go构建FunctionGraph HTTP函数
- 使用FunctionGraph HTTP函数处理gRPC请求
- 使用FunctionGraph部署DeepSeek-R1蒸馏模型
- 开发指南
- API参考
- SDK参考
-
常见问题
-
通用问题
- FunctionGraph是什么
- 使用FunctionGraph是否需要开通计算、存储、网络等服务?
- 使用FunctionGraph开发程序之后是否需要部署?
- 如何获取Token?
- FunctionGraph函数支持哪些编程语言?
- FunctionGraph函数分配磁盘空间有多少?
- FunctionGraph函数是否支持版本控制?
- 函数中如何读写文件?
- 使用CLI工具,如何配置网络代理?
- FunctionGraph函数是否支持扩展?
- IAM子账号使用FunctionGraph需要设置哪些权限?
- 如何制作基于ODBC驱动的Python依赖包用于查询数据库?
- FunctionGraph配额
- FunctionGraph函数支持哪些中文字体?
- FunctionGraph如何实现域名解析?
- 如何通过域名访问专享版APIG中注册的接口?
- 函数工作流的常见使用场景?
- 函数调用绑定在APIG的域名的服务,报域名无法解析?
- 同步函数工作流能否支持到内网最大带宽的同步传输 ?
- 单租户的VPC超过默认配额时,需要怎么做?
- 如何打印info、error、warn级别的日志?
- 函数是否可以把API的接口域名配置成自己的域名?
- 函数工作流是否支持修改运行时语言?
- 已创建的函数是否支持修改函数名称?
- 挂载文件系统时,报“failed to mount exist system path”,应如何处理?
- 如何获取上传的文件?
- 同步调用响应未收到的可能原因?
- os.system("command &")执行日志未采集,应如何处理?
- 自定义运行时,都能操作哪些目录?
- 运行时语言支持的python3.6和3.9具体指哪个版本?
- 用户想使用vpc功能,但不想配置VPC Administrator委托,应配置哪些授权项?
- 函数执行超时的可能原因有哪些?
- 如何获取函数代码?
- 是否有initializer的代码示例?
- 如何开启结构化日志查询
- 函数服务是否支持在函数中启动TCP的监听端口,通过EIP接收外部发送过来的TCP请求?
- FunctionGraph是否支持域名解析?
- 函数发起HTTP请求的源地址如何获取?
- 创建函数
- 触发器管理
- 依赖包管理
-
函数执行
- FunctionGraph函数的执行需要多长时间?
- FunctionGraph函数的执行包含了哪些过程?
- FunctiongGraph函数的并发处理过程是什么?
- FunctiongGraph函数如何处理长时间不执行的实例?
- 首次访问函数慢,如何优化?
- 怎样获取在函数运行过程中实际使用了多少内存?
- 为什么第一次请求会比较慢?
- 调用API时,报错怎么办?
- 如何读取函数的请求头?
- API同步执行函数接口,是否支持内网调用?
- 函数内存超限返回“runtime memory limit exceeded”,如何查看内存占用大小?
- 如何定位自定义镜像执行失败“CrashLoopBackOff”的原因?
- 用户使用相同的镜像名更新镜像,预留实例无法自动更新,会一直使用老镜像,应如何处理?
- 函数配置
- 函数访问外部资源
- 其他问题
- V1迁移V2相关问题
-
通用问题
-
更多文档
-
用户指南(阿布扎比区域)
- 产品介绍
- 快速入门
- 使用前必读
- 构建函数
- 配置函数
- 在线调试
- 配置触发器
- 调用函数
- 监控
- 函数管理
- 依赖包管理
- 预留实例管理
- 扩大资源配额
- 审计
-
常见问题
-
通用问题
- FunctionGraph是什么
- 使用FunctionGraph是否需要开通计算、存储、网络等服务?
- 使用FunctionGraph开发程序之后是否需要部署?
- FunctionGraph函数支持哪些编程语言?
- FunctionGraph函数分配磁盘空间有多少?
- FunctionGraph函数是否支持版本控制?
- 函数中如何读写文件?
- FunctionGraph函数是否支持扩展?
- IAM子帐号使用FunctionGraph需要设置哪些权限?
- 如何制作基于ODBC驱动的Python依赖包用于查询数据库?
- FunctionGraph配额
- FunctionGraph函数如何解析DNS内网域名?
- 容器镜像函数如何解析DNS内网域名?
- 如何通过域名访问专享版APIG中注册的接口?
- 函数工作流的常见使用场景?
- 函数调用绑定在APIG的域名的服务,报域名无法解析?
- 同步函数工作流能否支持到内网最大带宽的同步传输 ?
- 单租户的VPC超过默认配额时,需要怎么做?
- 如何打印info、error、warn级别的日志?
- 函数是否可以把API的接口域名配置成自己的域名?
- 函数工作流是否支持修改运行时语言?
- 已创建的函数是否支持修改函数名称?
- 挂载文件系统时,报“failed to mount exist system path”,应如何处理?
- 如何获取上传的文件?
- 同步调用响应未收到的可能原因?
- os.system("command &")执行日志未采集,应如何处理?
- 自定义运行时,都能操作哪些目录?
- 运行时语言支持的python3.6和3.9具体指哪个版本?
- 用户想使用vpc功能,但不想配置VPC Administrator委托,应配置哪些授权项?
- 函数执行超时的可能原因有哪些?
- 如何获取函数代码?
- 是否有initializer的代码示例?
- 如何开启结构化日志查询
- 函数服务是否支持在函数中启动TCP的监听端口,通过EIP接收外部发送过来的TCP请求?
- 创建函数
- 触发器管理
- 依赖包管理
-
函数执行
- FunctionGraph函数的执行需要多长时间?
- FunctionGraph函数的执行包含了哪些过程?
- FunctiongGraph函数的并发处理过程是什么?
- FunctiongGraph函数如何处理长时间不执行的实例?
- 首次访问函数慢,如何优化?
- 怎样获取在函数运行过程中实际使用了多少内存?
- 为什么第一次请求会比较慢?
- 调用API时,报错怎么办?
- 如何读取函数的请求头?
- 为什么函数实际使用内存大于预估内存,甚至触发OOM?
- 函数内存超限返回“runtime memory limit exceeded”,如何查看内存占用大小?
- 如何定位自定义镜像执行失败“CrashLoopBackOff”的原因?
- 用户使用相同的镜像名更新镜像,预留实例无法自动更新,会一直使用老镜像,应如何处理?
- 函数配置
- 函数访问外部资源
- 其他问题
-
通用问题
- API参考(阿布扎比区域)
- 开发指南(阿布扎比区域)
-
用户指南(吉隆坡区域)
- 产品介绍
- 快速入门
- 使用前必读
- 构建函数
- 配置函数
- 在线调试
- 配置触发器
- 调用函数
- 监控
- 函数管理
- 依赖包管理
- 预留实例管理
- 审计
-
常见问题
-
通用问题
- FunctionGraph是什么
- 使用FunctionGraph是否需要开通计算、存储、网络等服务?
- 使用FunctionGraph开发程序之后是否需要部署?
- FunctionGraph函数支持哪些编程语言?
- FunctionGraph函数分配磁盘空间有多少?
- FunctionGraph函数是否支持版本控制?
- 函数中如何读写文件?
- FunctionGraph函数是否支持扩展?
- IAM子账号使用FunctionGraph需要设置哪些权限?
- 如何制作基于ODBC驱动的Python依赖包用于查询数据库?
- FunctionGraph配额
- 容器镜像函数如何解析DNS内网域名?
- 如何通过域名访问专享版APIG中注册的接口?
- 函数工作流的常见使用场景?
- 函数调用绑定在APIG的域名的服务,报域名无法解析?
- 同步函数工作流能否支持到内网最大带宽的同步传输 ?
- 单租户的VPC超过默认配额时,需要怎么做?
- 如何打印info、error、warn级别的日志?
- 函数是否可以把API的接口域名配置成自己的域名?
- 函数工作流是否支持修改运行时语言?
- 已创建的函数是否支持修改函数名称?
- 挂载文件系统时,报“failed to mount exist system path”,应如何处理?
- 如何获取上传的文件?
- 同步调用响应未收到的可能原因?
- os.system("command &")执行日志未采集,应如何处理?
- 自定义运行时,都能操作哪些目录?
- 运行时语言支持的python3.6和3.9具体指哪个版本?
- 用户想使用vpc功能,但不想配置VPC Administrator委托,应配置哪些授权项?
- 函数执行超时的可能原因有哪些?
- 如何获取函数代码?
- 是否有initializer的代码示例?
- 如何开启结构化日志查询
- 函数服务是否支持在函数中启动TCP的监听端口,通过EIP接收外部发送过来的TCP请求?
- 创建函数
- 触发器管理
- 依赖包管理
-
函数执行
- FunctionGraph函数的执行需要多长时间?
- FunctionGraph函数的执行包含了哪些过程?
- FunctiongGraph函数的并发处理过程是什么?
- FunctiongGraph函数如何处理长时间不执行的实例?
- 首次访问函数慢,如何优化?
- 怎样获取在函数运行过程中实际使用了多少内存?
- 为什么第一次请求会比较慢?
- 调用API时,报错怎么办?
- 如何读取函数的请求头?
- 为什么函数实际使用内存大于预估内存,甚至触发OOM?
- 函数内存超限返回“runtime memory limit exceeded”,如何查看内存占用大小?
- 如何定位自定义镜像执行失败“CrashLoopBackOff”的原因?
- 用户使用相同的镜像名更新镜像,预留实例无法自动更新,会一直使用老镜像,应如何处理?
- 函数配置
- 函数访问外部资源
- 其他问题
-
通用问题
- 修订记录
- API参考(吉隆坡区域)
- 开发指南(吉隆坡区域)
-
用户指南(阿布扎比区域)
- 通用参考
链接复制成功!
开发事件函数
Go函数接口定义
FunctionGraph运行时支持Go 1.x版本,函数有明确的接口定义,如下所示:
func Handler (payload []byte, ctx context.RuntimeContext)
- 入口函数名(Handler):入口函数名称。
- 执行事件体(payload): 函数执行界面由用户输入的执行事件参数, 格式为JSON对象。
- 上下文环境(ctx):Runtime提供的函数执行上下文,其接口定义在SDK接口说明。
Go函数的函数执行入口参数格式为:与代码包中的可执行文件名保持一致。编译后的动态库文件名称必须与函数执行入口的插件名称保持一致,例如:动态库名称为testplugin.so,则函数执行入口命名为testplugin.Handler。可通过FunctionGraph控制台进入函数详情页的常规设置中进行配置或修改。
约束与限制
GetToken()、GetAccessKey()和GetSecretKey()方法返回的内容包含敏感信息,请谨慎使用,避免造成用户敏感信息的泄露。
SDK接口
FunctionGraph函数GoSDK提供了Event事件接口、Context接口和日志记录接口。Go SDK下载(Go SDK下载.sha256)。
- Event事件接口
Go SDK加入了触发器事件结构体定义,目前支持、DIS、DDS、SMN、TIMER、APIG、触发器。在需要使用触发器的场景时,编写相关代码更简单。
- APIG触发器相关字段说明
- APIGTriggerEvent相关字段说明
表1 APIGTriggerEvent相关字段说明
字段名
字段描述
IsBase64Encoded
Event中的body是否是base64编码
HttpMethod
Http请求方法
Path
Http请求路径
Body
Http请求body
PathParameters
所有路径参数
RequestContext
相关的APIG配置(APIGRequestContext对象)
Headers
Http请求头
QueryStringParameters
查询参数
UserData
APIG自定义认证中设置的userdata
- APIGTriggerResponse相关字段说明
表3 APIGTriggerResponse相关字段说明
字段名
字段描述
Body
消息体
Headers
最终返回的Http响应头
StatusCode
Http状态码,int类型
IsBase64Encoded
body是否经过base64编码,bool类型
说明:
APIGTriggerEvent提供GetRawBody()方法获取base64解码后的body体,相应的APIGTriggerResponse提供SetBase64EncodedBody()方法来设置base64编码的body体。
- APIGTriggerEvent相关字段说明
- DIS触发器相关字段说明
表4 DISTriggerEvent相关字段说明
字段名
字段描述
ShardID
分区ID
Message
DIS消息体(DISMessage结构)
Tag
函数版本
StreamName
通道名称
表5 DISMessage相关字段说明字段名
字段描述
NextPartitionCursor
下一个游标
Records
消息记录(DISRecord结构)
MillisBehindLatest
保留字段
- KAFKA触发器相关字段说明
表7 KAFKATriggerEvent相关字段说明
字段名
字段描述
InstanceId
实例ID
Records
消息记录(表8)
TriggerType
触发器类型,返回KAFKA
Region
region
EventTime
事件发生时间,秒数
EventVersion
事件版本
- SMN触发器相关字段说明
表9 SMNTriggerEvent相关字段说明
字段名
字段描述
Record
消息记录集合(SMNRecord结构)
表10 SMNRecord相关字段说明字段名
字段描述
EventVersion
事件版本(当前为1.0)
EventSubscriptionUrn
订阅URN
EventSource
事件源
Smn
SMN事件消息体(SMNBody结构)
- 定时触发器相关字段说明
表12 TimerTriggerEvent相关字段说明
字段名
字段描述
Version
版本名称(当前为“v1.0”)
Time
当前时间
TriggerType
触发器类型(“Timer”)
TriggerName
触发器名称
UserEvent
触发器附加信息
说明:
- 例如使用APIG触发器时,只需要把入口函数(假如函数名为handler)的第一个参数按照如下方式设置:handler(APIGTriggerEvent event, Context context)。相关约束条件请参考Base64解码和返回结构体的说明。
- 关于所有TriggerEvent,上面提到的TriggerEvent方法均有与之对应的set方法,建议在本地调试时使用;DIS和LTS均有对应的getRawData()方法,但无与之相应的setRawData()方法。
- APIG触发器相关字段说明
- Context接口
Context接口提供函数获取函数执行上下文,例如,用户委托的AccessKey/SecretKey、当前请求ID、函数执行分配的内存空间、CPU数等。
Context接口说明如表13所示。
表13 Context类上下文方法说明方法名
方法说明
getRequestID( )
获取请求ID。
getRemainingTimeInMilligetRunningTimeInSecondsSeconds ( )
获取函数剩余运行时间。
getAccessKey( )
获取用户委托的AccessKey(有效期24小时),使用该方法需要给函数配置委托。
当前函数工作流已停止维护Runtime SDK 中getAccessKey接口,您将无法使用getAccessKey获取临时AK。
getSecretKey( )
获取用户委托的SecretKey(有效期24小时),使用该方法需要给函数配置委托。
当前函数工作流已停止维护Runtime SDK 中getSecretKey接口,您将无法使用getSecretKey获取临时SK。
getSecurityAccessKey()
获取用户委托的SecurityAccessKey(有效期24小时),使用该方法需要给函数配置委托。
getSecuritySecretKey()
获取用户委托的SecuritySecretKey(有效期24小时),使用该方法需要给函数配置委托。
getSecurityToken()
获取用户委托的SecurityToken(有效期24小时),使用该方法需要给函数配置委托。
getUserData(string key)
通过key获取用户通过环境变量传入的值。
getFunctionName( )
获取函数名称。
getRunningTimeInSeconds ( )
获取函数超时时间。
getVersion( )
获取函数的版本。
getMemorySize( )
分配的内存。
getCPUNumber( )
获取函数占用的CPU资源。
getPackage( )
获取函数组。
getToken( )
获取用户委托的token(有效期24小时),使用该方法需要给函数配置委托。
getLogger( )
获取context提供的logger方法(默认会输出时间、请求ID等信息)。
getAlias
获取函数的别名
- 日志接口Go SDK日志接口日志说明如表14所示。
开发Go函数
登录已经安装了Go 1.x SDK的linux服务器,按照如下步骤进行编译和打包。(当前支持Ubuntu 14.04,Ubuntu 16.04,SuSE 11.3,SuSE 12.0,SuSE 12.1)
Go的版本支持go mod(go版本要求:1.11.1 及以上版本)
- 创建一个临时目录例如“/home/fssgo”,将FunctionGraph的Go RUNTIME SDK解压到新创建的目录,并开启go module开关,操作如下:
$ mkdir -p /home/fssgo
$ unzip functiongraph-go-runtime-sdk-1.0.1.zip -d /home/fssgo
$ export GO111MODULE="on"
- 在目录“/home/fssgo”下生成go.mod文件,操作如下,以模块名为test为例:
$ go mod init test
- 在目录“/home/fssgo”下编辑go.mod文件,添加加粗部分内容:
module test go 1.14 require ( huaweicloud.com/go-runtime v0.0.0-00010101000000-000000000000 ) replace ( huaweicloud.com/go-runtime => ./go-runtime )
- 在目录“/home/fssgo”下创建函数文件,并实现如下接口:
func Handler(payload []byte, ctx context.RuntimeContext) (interface{}, error)
其中payload为客户端请求的body数据,ctx为FunctionGraph提供的运行时上下文对象,具体提供的方法可以参考表13,以test.go为例:
package main import ( "fmt" "huaweicloud.com/go-runtime/go-api/context" "huaweicloud.com/go-runtime/pkg/runtime" "huaweicloud.com/go-runtime/events/apig" "huaweicloud.com/go-runtime/events/cts" "huaweicloud.com/go-runtime/events/dds" "huaweicloud.com/go-runtime/events/dis" "huaweicloud.com/go-runtime/events/kafka" "huaweicloud.com/go-runtime/events/lts" "huaweicloud.com/go-runtime/events/smn" "huaweicloud.com/go-runtime/events/timer" "encoding/json" ) func ApigTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var apigEvent apig.APIGTriggerEvent err := json.Unmarshal(payload, &apigEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", apigEvent.String()) apigResp := apig.APIGTriggerResponse{ Body: apigEvent.String(), Headers: map[string]string { "content-type": "application/json", }, StatusCode: 200, } return apigResp, nil } func CtsTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var ctsEvent cts.CTSTriggerEvent err := json.Unmarshal(payload, &ctsEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", ctsEvent.String()) return "ok", nil } func DdsTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var ddsEvent dds.DDSTriggerEvent err := json.Unmarshal(payload, &ddsEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", ddsEvent.String()) return "ok", nil } func DisTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var disEvent dis.DISTriggerEvent err := json.Unmarshal(payload, &disEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", disEvent.String()) return "ok", nil } func KafkaTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var kafkaEvent kafka.KAFKATriggerEvent err := json.Unmarshal(payload, &kafkaEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", kafkaEvent.String()) return "ok", nil } func LtsTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var ltsEvent lts.LTSTriggerEvent err := json.Unmarshal(payload, <sEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", ltsEvent.String()) return "ok", nil } func SmnTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var smnEvent smn.SMNTriggerEvent err := json.Unmarshal(payload, &smnEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", smnEvent.String()) return "ok", nil } func TimerTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var timerEvent timer.TimerTriggerEvent err := json.Unmarshal(payload, &timerEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } return timerEvent.String(), nil } func main() { runtime.Register(ApigTest) }
约束与限制:
- 如果函数返回的error参数不是nil,则会认为函数执行失败。
- 如果函数返回的error为nil,FunctionGraph仅支持返回如下几种类型的值。
[]byte:返回的HTTP响应Body内容为该字节数组内容。
string:返回的HTTP响应Body内容为该字符串内容。
其它:FunctionGraph会将返回值作为对象进行json编码,并将编码后的内容作为HTTP响应的Body,同时设置响应的"Content-Type"头为"application/json"。
- 上述例子使用APIG触发器的事件类型,如需使用其他触发器类型需要修改main函数的内容,例如使用CTS触发器则修改为runtime.Register(CtsTest),目前只支持注册一个入口。
- 当函数的事件源是APIG时,相关约束条件请参考Base64解码和返回结构体的说明。
- 编译和打包
函数代码编译完成后,按照如下方式编译和打包。
Go的版本不支持go mod(go版本低于1.11.1)
- 创建一个临时目录例如“/home/fssgo/src/huaweicloud.com”,将FunctionGraph的sdk Go RUNTIME SDK解压到新创建的目录,操作如下:
$ mkdir -p /home/fssgo/src/huaweicloud.com
$ unzip functiongraph-go-runtime-sdk-1.0.1.zip -d /home/fssgo/src/huaweicloud.com
- 在目录“/home/fssgo/src”下创建函数文件,并实现如下接口:
func Handler(payload []byte, ctx context.RuntimeContext) (interface{}, error)
其中payload为客户端请求的body数据,ctx为FunctionGraph提供的运行时上下文对象,具体提供的方法可以参考SDK接口,以test.go为例:
package main import ( "fmt" "huaweicloud.com/go-runtime/go-api/context" "huaweicloud.com/go-runtime/pkg/runtime" "huaweicloud.com/go-runtime/events/apig" "huaweicloud.com/go-runtime/events/cts" "huaweicloud.com/go-runtime/events/dds" "huaweicloud.com/go-runtime/events/dis" "huaweicloud.com/go-runtime/events/kafka" "huaweicloud.com/go-runtime/events/lts" "huaweicloud.com/go-runtime/events/smn" "huaweicloud.com/go-runtime/events/timer" "encoding/json" ) func ApigTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var apigEvent apig.APIGTriggerEvent err := json.Unmarshal(payload, &apigEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", apigEvent.String()) apigResp := apig.APIGTriggerResponse{ Body: apigEvent.String(), Headers: map[string]string { "content-type": "application/json", }, StatusCode: 200, } return apigResp, nil } func CtsTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var ctsEvent cts.CTSTriggerEvent err := json.Unmarshal(payload, &ctsEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", ctsEvent.String()) return "ok", nil } func DdsTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var ddsEvent dds.DDSTriggerEvent err := json.Unmarshal(payload, &ddsEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", ddsEvent.String()) return "ok", nil } func DisTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var disEvent dis.DISTriggerEvent err := json.Unmarshal(payload, &disEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", disEvent.String()) return "ok", nil } func KafkaTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var kafkaEvent kafka.KAFKATriggerEvent err := json.Unmarshal(payload, &kafkaEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", kafkaEvent.String()) return "ok", nil } func LtsTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var ltsEvent lts.LTSTriggerEvent err := json.Unmarshal(payload, <sEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", ltsEvent.String()) return "ok", nil } func SmnTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var smnEvent smn.SMNTriggerEvent err := json.Unmarshal(payload, &smnEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } ctx.GetLogger().Logf("payload:%s", smnEvent.String()) return "ok", nil } func TimerTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) { var timerEvent timer.TimerTriggerEvent err := json.Unmarshal(payload, &timerEvent) if err != nil { fmt.Println("Unmarshal failed") return "invalid data", err } return timerEvent.String(), nil } func main() { runtime.Register(ApigTest) }
约束与限制:
- 如果函数返回的error参数不是nil,则会认为函数执行失败。
- 如果函数返回的error为nil,FunctionGraph仅支持返回如下几种类型的值。
[]byte:返回的HTTP响应Body内容为该字节数组内容。
string:返回的HTTP响应Body内容为该字符串内容。
其它:FunctionGraph会将返回值作为对象进行json编码,并将编码后的内容作为HTTP响应的Body,同时设置响应的"Content-Type"头为"application/json"。
- 上述例子使用APIG触发器的事件类型,如需使用其他触发器类型需要修改main函数的内容,例如使用CTS触发器则修改为runtime.Register(CtsTest),目前只支持注册一个入口。
- 当函数的事件源是APIG时,相关约束条件请参考Base64解码和返回结构体的说明。
- 编译和打包
函数代码编译完成后,按照如下方式编译和打包。
- 设置GOROOT和GOPATH环境变量:
$ export GOROOT=/usr/local/go (假设Go安装到了/usr/local/go目录)
$ export PATH=$GOROOT/bin:$PATH
$ export GOPATH=/home/fssgo
- 编译:
$ go build -o handler test.go
说明:
“handler”作为函数执行入口可自定义,在FunctionGraph控制台的函数详情页设置中,可自行修改函数执行入口。
- 打包:
- 创建函数
登录FunctionGraph控制台,创建Go1.x函数,上传代码包fss_examples_go1.x.zip。
对于Go runtime,必须在编译之后打zip包,编译后的文件名称必须与函数执行入口的名称保持一致,例如:二进制文件名为handler,则“函数执行入口”命名为handler,Handler与步骤1中定义的函数保持一致。
- 测试函数
- 创建测试事件。
在函数详情页,单击“配置测试事件”,弹出“配置测试事件”页,输入测试信息如图1所示,单击“创建”。
- 在函数详情页,选择已配置测试事件,单击“测试”。
- 创建测试事件。
- 函数执行
函数执行结果分为三部分,分别为函数返回(由callback返回)、执行摘要、日志输出(由fmt.Println()方法获取的日志方法输出)。
- 设置GOROOT和GOPATH环境变量:
执行结果
执行结果由3部分组成:函数返回、执行摘要和日志。
参数项 |
执行成功 |
执行失败 |
---|---|---|
函数返回 |
返回函数中定义的返回信息。 |
返回包含错误信息和错误类型的JSON文件。格式如下: {
"errorMessage": "",
"errorType":"",
} errorMessage:Runtime返回的错误信息 errorType:错误类型 |
执行摘要 |
显示请求ID、配置内存、执行时长、实际使用内存和收费时长。 |
显示请求ID、配置内存、执行时长、实际使用内存和收费时长。 |
日志 |
打印函数日志,最多显示4KB的日志。 |
打印报错信息,最多显示4KB的日志。 |