在 Azure Functions 上使用 Quarkus 部署无服务器 Java 应用

在本文中,你将使用 Quarkus 开发、生成无服务器 Java 应用并将其部署到 Azure Functions。 本文使用 Quarkus Funqy 及其对 Java 的 Azure Functions HTTP 触发器的内置支持。 通过将 Quarkus 与 Azure Functions 配合使用,可在 Azure Functions 的规模和灵活性的基础上,获得 Quarkus 编程模型的强大功能。 完成后,你将在 Azure Functions 上运行无服务器 Quarkus 应用程序,并继续在 Azure 上监视应用。

先决条件

创建应用项目

使用以下命令克隆本文的示例 Java 项目。 该示例位于 GitHub 上。

git clone https://github.com/Azure-Samples/quarkus-azure
cd quarkus-azure
git checkout 2023-01-10
cd functions-quarkus

如果看到有关处于拆离的 HEAD 状态的消息,可以放心忽略此消息。 由于本文不需要任何提交,因此拆离的 HEAD 状态是合适的。

浏览示例函数。 打开 functions-quarkus/src/main/java/io/quarkus/GreetingFunction.java 文件。

运行以下命令。 @Funq 注释使方法(在本例中为 funqyHello)成为无服务器函数。

@Funq
public String funqyHello() {
    return "hello funqy";
}

Azure Functions Java 自带一组特定于 Azure 的注释,但是当你在 Azure Functions 上按照我们在此所述的简单方式使用 Quarkus 时,这些注释是不必要的。 有关 Azure Functions Java 注释的详细信息,请参阅 Azure Functions Java 开发人员指南

除非另行指定,否则函数的名称与方法名称相同。 还可使用以下命令通过注释的参数定义函数名称:

@Funq("alternateName")
public String funqyHello() {
    return "hello funqy";
}

该名称很重要。 它将成为调用函数的 REST URI 的一部分,如本文后面部分所示。

在本地测试函数

使用 mvn 在本地终端上运行 Quarkus 开发模式。 按照这种方式运行 Quarkus 可以使用后台编译实时重载。 修改 Java 文件和/或资源文件并刷新浏览器时,这些更改将自动生效。

浏览器刷新会触发工作区扫描。 如果扫描检测到任何更改,会重新编译 Java 文件并重新部署应用程序。 重新部署的应用程序为请求提供服务。 如果编译或部署存在任何问题,错误页会告知你。

在以下过程中,请将 yourResourceGroupName 替换为资源组名称。 函数应用名称在整个 Azure 中必须全局唯一。 资源组名称在订阅中必须全局唯一。 本文通过将资源组名称追加到函数名称来实现必要的唯一性。 请考虑在创建的任何必须唯一的名称前面附加唯一标识符。 一种有用的方法是使用首字母缩写,后跟今天的日期(格式为 mmdd)。

说明的这一部分不需要资源组,但稍后需要它。 为简单起见,Maven 项目要求定义属性。

  1. 调用 Quarkus 开发模式:

    cd functions-azure
    mvn -DskipTests -DresourceGroup=<yourResourceGroupName> quarkus:dev
    

    输出应如下所示:

    ...
    --/ __ \/ / / / _ | / _ \/ //_/ / / / __/ 
    -/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \   
    --\___\_\____/_/ |_/_/|_/_/|_|\____/___/   
    INFO  [io.quarkus] (Quarkus Main Thread) quarkus-azure-function 1.0-SNAPSHOT on JVM (powered by Quarkus xx.xx.xx.) started in 1.290s. Listening on: http://localhost:8080
    
    INFO  [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
    INFO  [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, funqy-http, smallrye-context-propagation, vertx]
    
    --
    Tests paused
    Press [r] to resume testing, [o] Toggle test output, [:] for the terminal, [h] for more options>
    
  2. 在本地终端上使用 CURL 命令访问函数:

    curl localhost:8080/api/funqyHello
    

    输出应如下所示:

    "hello funqy"
    

向函数添加依赖项注入

开放标准技术 Jakarta EE 上下文和依赖项注入 (CDI) 在 Quarkus 中提供依赖项注入。 有关注入(特别是 CDI)的大致一般概述,请参阅 Jakarta EE 教程

  1. 添加使用依赖项注入的新函数。

    在 functions-quarkus/src/main/java/io/quarkus 目录中创建 GreetingService.java 文件。 将以下代码用作文件的源代码:

    package io.quarkus;
    
    import javax.enterprise.context.ApplicationScoped;
    
    @ApplicationScoped
    public class GreetingService {
    
        public String greeting(String name) {
            return "Welcome to build Serverless Java with Quarkus on Azure Functions, " + name;
        }
    
    }
    

    保存文件。

    GreetingService 是实现 greeting() 方法的可注入 bean。 该方法返回带有 name 参数的 Welcome... 字符串消息。

  2. 打开现有的 functions-quarkus/src/main/java/io/quarkus/GreetingFunction.java 文件。 将类替换为以下代码以添加新的 gService 字段和 greeting 方法:

    package io.quarkus;
    
    import javax.inject.Inject;
    import io.quarkus.funqy.Funq;
    
    public class GreetingFunction {
    
        @Inject
        GreetingService gService;
    
        @Funq
        public String greeting(String name) {
            return gService.greeting(name);
        }
    
        @Funq
        public String funqyHello() {
            return "hello funqy";
        }
    
    }
    

    保存文件。

  3. 在本地终端上使用 curl 命令访问新的 greeting 函数:

    curl -d '"Dan"' -X POST localhost:8080/api/greeting
    

    输出应如下所示:

    "Welcome to build Serverless Java with Quarkus on Azure Functions, Dan"
    

    重要

    通过实时编码(也称为“开发模式”)可运行应用并即时进行更改。 Quarkus 将在进行更改时自动重新编译并重新加载应用。 这是一种强大而高效的开发风格,你将在本文中使用它。

    在继续下一步之前,请选择 Ctrl+C 停止 Quarkus 开发模式。

将应用部署到 Azure

  1. 如果尚未这样做,请使用以下 az login 命令登录到 Azure 订阅,并遵照屏幕上的指示操作:

    az login
    

    注意

    如果多个 Azure 租户与你的 Azure 凭据关联,必须指定要登录到哪个租户。 可使用 --tenant 选项来完成此操作。 例如:az login --tenant contoso.partner.onmschina.cn

    在 Web 浏览器中继续该过程。 如果没有可用的 Web 浏览器或 Web 浏览器无法打开,请通过 az login --use-device-code 使用设备代码流。

    成功登录后,本地终端上的输出应如下所示:

    xxxxxxx-xxxxx-xxxx-xxxxx-xxxxxxxxx 'Microsoft'
    [
        {
            "cloudName": "AzureChinaCloud",
            "homeTenantId": "xxxxxx-xxxx-xxxx-xxxx-xxxxxxx",
            "id": "xxxxxx-xxxx-xxxx-xxxx-xxxxxxxx",
            "isDefault": true,
            "managedByTenants": [],
            "name": "Contoso account services",
            "state": "Enabled",
            "tenantId": "xxxxxxx-xxxx-xxxx-xxxxx-xxxxxxxxxx",
            "user": {
            "name": "user@contoso.com",
            "type": "user"
            }
        }
    ]
    
  2. 生成函数并将其部署到 Azure。

    在上一步中生成的 pom.xml 文件使用 azure-functions-maven-plugin。 运行 mvn install 会生成 azure-functions-maven-plugin 所需的配置文件和分段目录。 对于 yourResourceGroupName,请使用前面所用的值。

    mvn clean install -DskipTests -DtenantId=<your tenantId from shown previously> -DresourceGroup=<yourResourceGroupName> azure-functions:deploy
    
  3. 在部署期间,登录到 Azure。 azure-functions-maven-plugin 插件配置为在每次部署项目时提示 Azure 登录。 在生成期间,将显示如下所示的输出:

    [INFO] Auth type: DEVICE_CODE
    To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code AXCWTLGMP to authenticate.
    

    按照输出所示操作,并使用浏览器和提供的设备代码向 Azure 进行身份验证。 还有许多其他身份验证和配置选项可用。 可在 Azure Functions:配置详细信息中获取 azure-functions-maven-plugin 的完整参考文档。

  4. 身份验证后,应会继续并完成生成。 确保输出在末尾附近包含 BUILD SUCCESS

    Successfully deployed the artifact to https://quarkus-demo-123451234.chinacloudsites.cn
    

    还可以在输出日志中找到在 Azure 上触发函数的 URL:

    [INFO] HTTP Trigger Urls:
    [INFO] 	 quarkus : https://quarkus-azure-functions-http-archetype-20220629204040017.chinacloudsites.cn/api/{*path}
    

    部署需要一段时间才能完成。 在此期间,让我们来探索 Azure 门户中的 Azure Functions。

访问和监视 Azure 上的无服务器函数

登录到门户,并确保选择了与在 Azure CLI 中使用的相同租户和订阅。

  1. 在 Azure 门户顶部的搜索栏上键入“函数应用”,然后按 Enter 键。 应会部署你的函数应用,并显示名称 <yourResourceGroupName>-function-quarkus

    Screenshot that shows the function app in the portal.

  2. 选择函数应用以显示详细信息,例如“位置”、“订阅”、“URL”、“指标”和“应用服务计划”。 然后选择“URL”值。

    Screenshot that shows a URL and other function app details.

  3. 确认欢迎页显示函数应用“已启动且正在运行”。

    Screenshot that shows the welcome page for a function app.

  4. 在本地终端上使用以下 curl 命令调用 greeting 函数。

    重要

    请将 YOUR_HTTP_TRIGGER_URL 替换为在 Azure 门户或输出中找到的你自己的函数 URL。

    curl -d '"Dan on Azure"' -X POST https://YOUR_HTTP_TRIGGER_URL/api/greeting
    

    输出应如下所示:

    "Welcome to build Serverless Java with Quarkus on Azure Functions, Dan on Azure"
    

    还可使用以下 curl 命令访问另一个函数 (funqyHello):

    curl https://YOUR_HTTP_TRIGGER_URL/api/funqyHello
    

    输出应与前面观察到的输出相同:

    "hello funqy"
    

    如果你要在 Azure 门户中执行基本指标功能,请尝试在 shell for 循环中调用该函数:

    for i in {1..100}; do curl -d '"Dan on Azure"' -X POST https://YOUR_HTTP_TRIGGER_URL/api/greeting; done
    

    一段时间后,门户中会显示一些指标数据。

    Screenshot that shows function metrics in the portal.

在门户中打开 Azure 函数后,可通过门户访问以下更多功能:

清理资源

如果不需要这些资源,可通过在本地终端上运行以下命令将其删除:

az group delete --name <yourResourceGroupName> --yes

后续步骤

本文介绍了如何执行以下操作:

  • 运行 Quarkus 开发模式。
  • 使用 azure-functions-maven-plugin 将 Funqy 应用部署到 Azure Functions。
  • 检查门户中函数的性能。

若要详细了解 Azure Functions 和 Quarkus,请查看以下文章和参考资料: