第 11 章 功能开发参考指南
11.1. 开发 Quarkus 功能
创建 Quarkus 功能项目后,您可以修改提供的模板文件,以将业务逻辑添加到您的功能中。这包括配置功能调用和返回的标头和状态代码。
11.1.1. 先决条件
- 在开发功能前,您必须完成 配置 OpenShift Serverless 功能 中的设置步骤。
11.1.2. Quarkus 功能模板结构
使用 Knative (kn
) CLI 创建 Quarkus 功能时,项目目录类似于典型的 Maven 项目。另外,项目还包含用于配置功能的 func.yaml
文件。
http
和 event
触发器功能具有相同的模板结构:
模板结构
. ├── func.yaml 1 ├── mvnw ├── mvnw.cmd ├── pom.xml 2 ├── README.md └── src ├── main │ ├── java │ │ └── functions │ │ ├── Function.java 3 │ │ ├── Input.java │ │ └── Output.java │ └── resources │ └── application.properties └── test └── java └── functions 4 ├── FunctionTest.java └── NativeFunctionIT.java
- 1
- 用于确定镜像名称和 registry。
- 2
- 项目对象模型(POM)文件包含项目配置,如依赖项的相关信息。您可以通过修改此文件来添加额外的依赖项。
其他依赖项示例
... <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13</version> <scope>test</scope> </dependency> <dependency> <groupId>org.assertj</groupId> <artifactId>assertj-core</artifactId> <version>3.8.0</version> <scope>test</scope> </dependency> </dependencies> ...
依赖项在第一次编译时下载。
- 3
- 功能项目必须包含标有
@Funq
的 Java 方法。您可以将此方法放置在Function.java
类中。 - 4
- 包含可用于在本地测试功能的简单测试案例。
11.1.3. 关于调用 Quarkus 功能
您可以创建一个 Quarkus 项目来响应云事件,或创建响应简单 HTTP 请求的 Quarkus 项目。Knative 中的云事件作为 POST 请求通过 HTTP 传输,因此任一功能类型都可以侦听和响应传入的 HTTP 请求。
收到传入请求时,通过允许类型的实例调用 Quarkus 函数。
调用方法 | 实例中包含的数据类型 | 数据示例 |
---|---|---|
HTTP POST 请求 | 请求正文中的 JSON 对象 |
|
HTTP GET 请求 | 查询字符串中的数据 |
|
|
|
|
以下示例显示了接收并处理上表中列出的 customerId
和 productId
购买数据的函数:
Quarkus 功能示例
public class Functions { @Funq public void processPurchase(Purchase purchase) { // process the purchase } }
包含购买数据的对应 Purchase
JavaBean 类如下:
类示例
public class Purchase { private long customerId; private long productId; // getters and setters }
11.1.3.1. 调用示例
以下示例代码定义了名为 withBeans
、withCloudEvent
和 withBinary
的三个功能;
示例
import io.quarkus.funqy.Funq; import io.quarkus.funqy.knative.events.CloudEvent; public class Input { private String message; // getters and setters } public class Output { private String message; // getters and setters } public class Functions { @Funq public Output withBeans(Input in) { // function body } @Funq public CloudEvent<Output> withCloudEvent(CloudEvent<Input> in) { // function body } @Funq public void withBinary(byte[] in) { // function body } }
Functions
类的 withBeans
功能可以通过以下方法调用:
带有 JSON 正文的 HTTP POST 请求:
$ curl "http://localhost:8080/withBeans" -X POST \ -H "Content-Type: application/json" \ -d '{"message": "Hello there."}'
带有查询参数的 HTTP GET 请求:
$ curl "http://localhost:8080/withBeans?message=Hello%20there." -X GET
二进制编码中的
CloudEvent
对象:$ curl "http://localhost:8080/" -X POST \ -H "Content-Type: application/json" \ -H "Ce-SpecVersion: 1.0" \ -H "Ce-Type: withBeans" \ -H "Ce-Source: cURL" \ -H "Ce-Id: 42" \ -d '{"message": "Hello there."}'
结构化编码中的
CloudEvent
对象:$ curl http://localhost:8080/ \ -H "Content-Type: application/cloudevents+json" \ -d '{ "data": {"message":"Hello there."}, "datacontenttype": "application/json", "id": "42", "source": "curl", "type": "withBeans", "specversion": "1.0"}'
与 withBeans
函数类似,可以利用 CloudEvent
对象来调用 Functions
类的 withCloudEvent
功能。但是,与 Beans
不同,CloudEvent
无法通过普通 HTTP 请求来调用。
Functions
类的 withBinary
功能可通过以下方式调用:
二进制编码中的
CloudEvent
对象:$ curl "http://localhost:8080/" -X POST \ -H "Content-Type: application/octet-stream" \ -H "Ce-SpecVersion: 1.0"\ -H "Ce-Type: withBinary" \ -H "Ce-Source: cURL" \ -H "Ce-Id: 42" \ --data-binary '@img.jpg'
结构化编码中的
CloudEvent
对象:$ curl http://localhost:8080/ \ -H "Content-Type: application/cloudevents+json" \ -d "{ \"data_base64\": \"$(base64 --wrap=0 img.jpg)\", \"datacontenttype\": \"application/octet-stream\", \"id\": \"42\", \"source\": \"curl\", \"type\": \"withBinary\", \"specversion\": \"1.0\"}"
11.1.4. CloudEvent 属性
如果您需要读取或写入 CloudEvent 的属性,如 type
或 subject
,您可以使用 CloudEvent<T>
通用接口和 CloudEventBuilder
构建器。<T>
类型参数必须是允许的类型之一。
在以下示例中,CloudEventBuilder
用于返回处理订购的成功或失败:
public class Functions { private boolean _processPurchase(Purchase purchase) { // do stuff } public CloudEvent<Void> processPurchase(CloudEvent<Purchase> purchaseEvent) { System.out.println("subject is: " + purchaseEvent.subject()); if (!_processPurchase(purchaseEvent.data())) { return CloudEventBuilder.create() .type("purchase.error") .build(); } return CloudEventBuilder.create() .type("purchase.success") .build(); } }
11.1.5. Quarkus 功能返回值
功能可以从允许类型列表中返回任何类型的实例。另外,他们可以返回 Uni<T>
类型,其中 <T>
类型参数可以是允许的类型的任何类型。
如果函数调用异步 API,因为返回的对象以与接收对象相同的格式序列化,Uni<T>
类型很有用。例如:
- 如果函数收到 HTTP 请求,则返回的对象将在 HTTP 响应的正文中发送。
-
如果函数通过二进制编码收到
CloudEvent
对象,则返回的对象将在二进制编码的CloudEvent
对象的 data 属性中发送。
以下示例显示了获取购买列表的功能:
示例命令
public class Functions { @Funq public List<Purchase> getPurchasesByName(String name) { // logic to retrieve purchases } }
- 通过 HTTP 请求调用此功能将生成 HTTP 响应,其中包含响应正文中的订购列表。
-
通过传入的
CloudEvent
对象调用此功能可生成CloudEvent
响应,并在data
属性中包括一个订购列表。
11.1.5.1. 允许的类型
功能的输入和输出可以是 void
、String
、或 byte[]
类型。此外,它们也可以是原语类型及其打包程序,例如 int
和 Integer
。它们也可以是以下复杂的对象:Javabeans、映射、列表、数组和特殊的 CloudEvents<T>
类型。
映射、列出、数组、CloudEvents<T>
类型的 <T>
类型参数以及 Javabeans 的属性只能是此处列出的类型。
示例
public class Functions { public List<Integer> getIds(); public Purchase[] getPurchasesByName(String name); public String getNameById(int id); public Map<String,Integer> getNameIdMapping(); public void processImage(byte[] img); }
11.1.6. 测试 Quarkus 功能
Quarkus 功能可以在您的计算机上进行本地测试。在使用 kn func create
创建功能时创建的默认项目中,有 src/test/
目录,其中包含基本的 Maven 测试。这些测试可以根据需要扩展。
先决条件
- 您已创建了 Quarkus 功能。
-
已安装 Knative (
kn
) CLI。
流程
- 导航到您的功能的项目文件夹。
运行 Maven 测试:
$ ./mvnw test
11.1.7. 覆盖存活度和就绪度探测值
您可以覆盖 Quarkus 功能的
值。这可让您配置在功能上执行的健康检查。
存活度和就绪度探测
先决条件
- 在集群中安装了 OpenShift Serverless Operator 和 Knative Serving。
-
已安装 Knative (
kn
) CLI。 -
已使用
kn func create
创建功能。
流程
使用您自己的值覆盖
/health/liveness
和/health/readiness
路径。您可以通过在func.yaml
文件中设置QUARKUS_SMALLRYE_HEALTH_LIVENESS_PATH
和QUARKUS_SMALLRYE_HEALTH_READINESS_PATH
环境变量来完成此操作。要使用功能源覆盖路径,更新
src/main/resources/application.properties
文件中的路径属性:quarkus.smallrye-health.root-path=/health 1 quarkus.smallrye-health.liveness-path=alive 2 quarkus.smallrye-health.readiness-path=ready 3
要使用环境变量覆盖路径,请在
func.yaml
文件的构建块中定义路径变量:build: builder: s2i buildEnvs: - name: QUARKUS_SMALLRYE_HEALTH_LIVENESS_PATH value: alive 1 - name: QUARKUS_SMALLRYE_HEALTH_READINESS_PATH value: ready 2
将新端点添加到
func.yaml
文件中,以便它们正确绑定到 Knative 服务的容器:deploy: healthEndpoints: liveness: /health/alive readiness: /health/ready