1. 概述

Quarkus 允许我们快速构建小型应用,并实现极快的启动时间和更低的首次接触响应时间。

在这个教程中,我们将探讨Quarkus框架的扩展——Funqy

2. Funqy是什么?

Quarkus Funqy 是一个旨在提供可移植的Java API的解决方案,它让我们能够编写无服务器函数。我们可以轻松地将这些函数部署到AWS Lambda、Azure Functions、Google Cloud Functions等FAAS(函数即服务)环境,也可以作为独立服务使用。

3. 实现

让我们使用Quarkus Funky创建一个简单的问候函数,并在FAAS基础设施上部署它。我们可以通过Quarkus web界面创建项目,也可以通过执行以下命令使用Maven创建:

$ mvn io.quarkus:quarkus-maven-plugin:2.7.7.Final:create
  -DprojectGroupId=com.baeldung.quarkus
  -DprojectArtifactId=quarkus-funqy-project
  -Dextensions="funqy-http"

我们使用的是quarkus-maven-plugin来创建项目,它会生成一个包含功能类的项目骨架。

让我们将这个项目导入IDE,以获得如下所示的结构:

3.1. Java代码

打开MyFunctions.java文件并查看内容:

public class MyFunctions {

    @Funq
    public String fun(FunInput input) {
        return String.format("Hello %s!", input != null ? input.name : "Funqy");
    }

    public static class FunInput {
        public String name;
        // constructors, getters, setters
    }
}

@Funq注解标记的方法是入口点函数。 函数最多只能有一个参数,可能有返回值也可能没有。默认函数名称是注解方法名,我们可以通过在@Funq注解中传入名称字符串来更新它。

让我们将名称更改为GreetUser,并添加一个简单的日志语句:

@Funq("GreetUser")
public String fun(FunInput input) {
    log.info("Function Triggered");
    ...
}

4. 部署

现在打开MyFunctionTest.java类,更新所有测试用例中提到的路径方法名。首先,我们本地运行以下命令来运行它:

$ ./mvnw quarkus:dev

它将启动服务器并执行测试用例。

使用curl进行测试:

$ curl -X POST 'http://localhost:8080/GreetUser'
--header 'Content-Type: application/json'
--data-raw '{
    "name": "Baeldung"
}'

它将给出问候响应。

4.1. Kubernetes Knative

接下来,我们在Kubernetes Knative上部署它。在pom.xml文件中添加quarkus-funqy-knative-events依赖:

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-funqy-knative-events</artifactId>
    <version>3.0.0.Alpha3</version>
</dependency>

让我们用单元测试验证一下:

@Test
public void givenFunctionAPI_whenCallWithEvent_thenShouldReturn200() {
    RestAssured.given().contentType("application/json")
      .header("ce-specversion", "1.0")
      .header("ce-id", UUID.randomUUID().toString())
      .header("ce-type", "GreetUser")
      .header("ce-source", "test")
      .body("{ \"name\": \"Baeldung\" }")
      .post("/")
      .then().statusCode(200);
}

现在,我们构建和打包我们的应用程序:

$ ./mvnw install
$ docker build -f src/main/docker/Dockerfile.jvm -t
  <<dockerAccountName>>/quarkus-funqy-project .
$ docker push <<ourDockerAccountName>>/quarkus-funqy-project

src/main/kubernetes目录下创建用于资源创建的Kubernetes Knative配置文件knative.yaml

apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: quarkus-funqy-project
spec:
  template:
    metadata:
      name: quarkus-funqy-project-v1
    spec:
      containers:
        - image: docker.io/<<dockerAccountName>>/quarkus-funqy-project

只需创建一个broker,broker事件配置YAML文件,并部署它们即可。

让我们创建一个knative-trigger.yaml文件:

apiVersion: eventing.knative.dev/v1
kind: Trigger
metadata:
  name: baeldung-event
spec:
  broker: baeldung
  filter:
    attributes:
      type: GreetUser
  subscriber:
    ref:
      apiVersion: serving.knative.dev/v1
      kind: Service
      name: quarkus-funqy-project
$ kn broker create baeldung
$ kubectl apply -f src/main/kubernetes/knative.yaml
$ kubectl apply -f src/main/kubernetes/knative-trigger.yaml

检查Pod和Pod日志,因为Pod应该正在运行。如果我们不发送任何事件,Pod会自动缩放到0。获取broker的URL,以便发送事件:

$ kubectl get broker baeldung -o jsonpath='{.status.address.url}'

现在,可以从任何Pod向这个URL发送事件,如果我们的Quarkus应用已经关闭,它将启动一个新的Pod。我们还可以检查日志以确认函数是否被触发:

$ curl -v "<<our_broker_url>>" 
  -X POST
  -H "Ce-Id: 1234"
  -H "Ce-Specversion: 1.0"
  -H "Ce-Type: GreetUser"
  -H "Ce-Source: curl"
  -H "Content-Type: application/json"
  -d "{\"name\":\"Baeldung\"}"

4.2. 云部署

我们也可以更新应用以在云平台上部署,但每个云部署只能导出一个Funqy函数。如果我们的应用有多重Funqy方法,可以在application.properties文件中添加以下内容(将GreetUser替换为活动函数名称)来指定活动函数:

quarkus.funqy.export=GreetUser

5. 总结

在这篇文章中,我们了解到Quarkus Funqy是一个强大的补充,它帮助我们在无服务器基础设施上轻松运行Java函数。我们了解了Quarkus Funqy的工作原理,以及如何在无服务器环境中实现、部署和测试它。

如往常一样,示例的完整源代码可在GitHub上找到:GitHub链接