×

OpenShift Serverless Functions with Go 仅为技术预览功能。技术预览功能不受 Red Hat 生产服务级别协议 (SLA) 的支持,并且可能功能不完整。Red Hat 不建议在生产环境中使用它们。这些功能可让客户尽早访问即将推出的产品功能,从而能够在开发过程中测试功能并提供反馈。

有关 Red Hat 技术预览功能的支持范围的更多信息,请参见 技术预览功能支持范围

在您创建 Go 函数项目后,您可以修改提供的模板文件以向您的函数添加业务逻辑。这包括配置函数调用以及返回的标头和状态代码。

先决条件

Go 函数模板结构

使用 Knative (kn) CLI 创建 Go 函数时,项目目录看起来像一个典型的 Go 项目。唯一的例外是额外的func.yaml配置文件,用于指定镜像。

Go 函数的限制很少。唯一的要求是您的项目必须在function模块中定义,并且必须导出函数Handle()

httpevent触发函数具有相同的模板结构。

模板结构
fn
├── README.md
├── func.yaml (1)
├── go.mod (2)
├── go.sum
├── handle.go
└── handle_test.go
1 func.yaml配置文件用于确定镜像名称和注册表。
2 您可以向go.mod文件添加任何所需的依赖项,其中可以包含其他本地 Go 文件。构建项目以进行部署时,这些依赖项将包含在生成的运行时容器镜像中。
添加依赖项的示例
$ go get gopkg.in/[email protected]

关于调用 Go 函数

使用 Knative (kn) CLI 创建函数项目时,您可以生成一个响应 CloudEvents 的项目,或者生成一个响应简单 HTTP 请求的项目。Go 函数的调用方法不同,具体取决于它们是由 HTTP 请求还是 CloudEvent 触发。

由 HTTP 请求触发的函数

当收到传入的 HTTP 请求时,函数会以标准 Go Context 作为第一个参数调用,后跟 http.ResponseWriterhttp.Request 参数。您可以使用标准 Go 技术访问请求,并为您的函数设置相应的 HTTP 响应。

HTTP 响应示例
func Handle(ctx context.Context, res http.ResponseWriter, req *http.Request) {
  // Read body
  body, err := ioutil.ReadAll(req.Body)
  defer req.Body.Close()
  if err != nil {
	http.Error(res, err.Error(), 500)
	return
  }
  // Process body and function logic
  // ...
}

由云事件触发的函数

当收到传入的云事件时,该事件将由 CloudEvents Go SDK 调用。调用使用 Event 类型作为参数。

您可以利用 Go Context 作为函数契约中的可选参数,如支持的函数签名列表所示。

支持的函数签名
Handle()
Handle() error
Handle(context.Context)
Handle(context.Context) error
Handle(cloudevents.Event)
Handle(cloudevents.Event) error
Handle(context.Context, cloudevents.Event)
Handle(context.Context, cloudevents.Event) error
Handle(cloudevents.Event) *cloudevents.Event
Handle(cloudevents.Event) (*cloudevents.Event, error)
Handle(context.Context, cloudevents.Event) *cloudevents.Event
Handle(context.Context, cloudevents.Event) (*cloudevents.Event, error)

CloudEvent 触发器示例

收到一个云事件,该事件在 data 属性中包含一个 JSON 字符串。

{
  "customerId": "0123456",
  "productId": "6543210"
}

要访问此数据,必须定义一个结构体,该结构体映射云事件数据中的属性,并从传入的事件中检索数据。以下示例使用 Purchase 结构体。

type Purchase struct {
  CustomerId string `json:"customerId"`
  ProductId  string `json:"productId"`
}
func Handle(ctx context.Context, event cloudevents.Event) (err error) {

  purchase := &Purchase{}
  if err = event.DataAs(purchase); err != nil {
	fmt.Fprintf(os.Stderr, "failed to parse incoming CloudEvent %s\n", err)
	return
  }
  // ...
}

或者,可以使用 Go encoding/json 包直接将云事件作为字节数组形式的 JSON 进行访问。

func Handle(ctx context.Context, event cloudevents.Event) {
  bytes, err := json.Marshal(event)
  // ...
}

Go 函数返回值

由 HTTP 请求触发的函数可以直接设置响应。您可以使用 Go http.ResponseWriter 配置函数来执行此操作。

HTTP 响应示例
func Handle(ctx context.Context, res http.ResponseWriter, req *http.Request) {
  // Set response
  res.Header().Add("Content-Type", "text/plain")
  res.Header().Add("Content-Length", "3")
  res.WriteHeader(200)
  _, err := fmt.Fprintf(res, "OK\n")
  if err != nil {
	fmt.Fprintf(os.Stderr, "error or response write: %v", err)
  }
}

由云事件触发的函数可能返回空值、errorCloudEvent 以便将事件推送到 Knative Eventing 系统。在这种情况下,必须为云事件设置唯一的 ID、正确的 SourceType。数据可以从定义的结构体或 map 中填充。

CloudEvent 响应示例
func Handle(ctx context.Context, event cloudevents.Event) (resp *cloudevents.Event, err error) {
  // ...
  response := cloudevents.NewEvent()
  response.SetID("example-uuid-32943bac6fea")
  response.SetSource("purchase/getter")
  response.SetType("purchase")
  // Set the data from Purchase type
  response.SetData(cloudevents.ApplicationJSON, Purchase{
	CustomerId: custId,
	ProductId:  prodId,
  })
  // OR set the data directly from map
  response.SetData(cloudevents.ApplicationJSON, map[string]string{"customerId": custId, "productId": prodId})
  // Validate the response
  resp = &response
  if err = resp.Validate(); err != nil {
	fmt.Printf("invalid event created. %v", err)
  }
  return
}

测试 Go 函数

Go 函数可以在您计算机上本地进行测试。使用 kn func create 创建函数时创建的默认项目中,有一个 handle_test.go 文件,其中包含一些基本测试。可以根据需要扩展这些测试。

先决条件
  • OpenShift Serverless Operator 和 Knative Serving 已安装在集群上。

  • 您已安装 Knative (kn) CLI。

  • 您已使用 kn func create 创建了一个函数。

步骤
  1. 导航到函数的 test 文件夹。

  2. 运行测试

    $ go test

后续步骤