教程:使用 Linux 和 PostgreSQL 上的Azure 应用服务生成 Quarkus Web 应用

本教程介绍如何在连接到 PostgreSQL 数据库的 Azure 应用服务中生成、配置和部署安全 Quarkus 应用程序(使用 Azure Database for PostgreSQL)。 Azure 应用服务是一种可缩放程度高、支持自修补的 Web 托管服务,可轻松地在 Windows 或 Linux 上部署应用。 完成本教程后,Linux 上的 Azure 应用服务上将会运行一个 Quarkus 应用。

将数据存储在 PostgreSQL 中的 Quarkus 应用屏幕截图。

若要完成本教程,你需要:

跳到末尾

可以快速部署本教程中的示例应用,并查看它是否在 Azure 中运行。 只需在 Azure Cloud Shell 中运行以下命令,然后按照提示操作:

mkdir msdocs-quarkus-postgresql-sample-app
cd msdocs-quarkus-postgresql-sample-app
azd init --template msdocs-quarkus-postgresql-sample-app
azd up

1.运行示例

首先,将示例数据驱动的应用设置为起点。 为方便起见,示例存储库“使用 Panache 和 RESTEasy 的 Hibernate ORM”包含一个开发容器配置。 开发容器包含开发应用程序所需的所有内容,包括示例应用程序所需的数据库、缓存和所有环境变量。 开发容器可以在 GitHub codespace 中运行,这意味着可使用 Web 浏览器在任何计算机上运行示例。

步骤 1:在新浏览器窗口中:

  1. 登录到 GitHub 帐户。
  2. 导航到 https://github.com/Azure-Samples/msdocs-quarkus-postgresql-sample-app/fork
  3. 取消选择“仅复制主分支”。 需要所有分支。
  4. 选择“创建分支”。

显示如何创建示例 GitHub 存储库分支的屏幕截图。

步骤 2:在 GitHub 分支中:

  1. 为起始分支选择“”>“starter-no-infra”。 此分支仅包含示例项目,不包含与 Azure 相关的文件或配置。
  2. 选择“代码”>“在主分支上创建 codespace”。 设置 codespace 需要几分钟时间。

显示如何在 GitHub 中创建 codespace 的屏幕截图。

步骤 3:在 codespace 终端中

  1. 运行 mvn quarkus:dev
  2. 看到通知 Your application running on port 8080 is available. 时,选择“在浏览器中打开”。 如果看到端口为 5005 的通知,请跳过该通知。 应在新的浏览器选项卡中看到该示例应用程序。要停止 Quarkus 开发服务器,键入 Ctrl+C

显示如何在 GitHub codespace 中运行示例应用程序的屏幕截图。

有关如何创建 Quarkus 示例应用程序的详细信息,请参阅 Quarkus 文档“使用 Panache 的简化 Hibernate ORM”“在 Quarkus 中配置数据源”

遇到问题? 检查故障排除部分

2.创建应用服务和 PostgreSQL

首先,创建 Azure 资源。 本教程中使用的步骤创建一组默认安全的资源,其中包括应用服务和 Azure Database for PostgreSQL。 此创建过程中,你将指定:

  • Web 应用的名称。 此名称用作 Web 应用的 DNS 名称的一部分,其格式为 https://<app-name>.chinacloudsites.cn
  • “区域”,在世界上以物理方式运行应用。
  • 应用的运行时堆栈。 在此处选择要用于应用的 PHP 版本。
  • 应用的托管计划。 它是定价层,包括应用的一组功能和缩放容量。
  • 应用的资源组。 使用资源组可将应用程序所需的所有 Azure 资源分组到一个逻辑容器中。

登录到 Azure 门户并按照以下步骤创建 Azure 应用服务资源。

步骤 1:在 Azure 门户中:

  1. 在 Azure 门户顶部的搜索栏中,输入“Web 应用数据库”。
  2. 选择“市场”标题下标记为“Web 应用 + 数据库”的项目。 还可以直接导航到创建向导

显示如何使用顶部工具栏中的搜索框查找“Web 应用 + 数据库”创建向导的屏幕截图。

步骤 2:在“创建 Web 应用 + 数据库”页上,按下面所述填写表单。

  1. 资源组:选择“新建”并使用 msdocs-quarkus-postgres-tutorial 名称
  2. 区域:你附近的任何 Azure 区域。
  3. 名称:msdocs-quarkus-postgres-XYZ,其中 XYZ 是任意三个随机字符。 该名称在 Azure 中必须唯一。
  4. 运行时堆栈Java 17
  5. Java Web 服务器堆栈:Java SE(嵌入式 Web 服务器)
  6. 数据库:PostgreSQL - 灵活服务器。 默认情况下,服务器名称和数据库名称设置为适当的值。
  7. 托管计划基本。 准备就绪后,可以稍后纵向扩展到生产定价层。
  8. 选择“查看 + 创建”。
  9. 验证完成后,选择“创建”。

显示如何在“Web 应用 + 数据库”向导中配置新应用程序和数据库的屏幕截图。

步骤 3:该部署需要数分钟才能完成。 部署完成后,选择“转到资源”按钮。 这将直接转到应用服务应用,但会创建以下资源:

  • 资源组:所有已创建资源的容器。
  • 应用服务计划:为应用服务定义计算资源。 将创建基本层中的 Linux 计划。
  • 应用服务:表示应用并在应用服务计划中运行。
  • 虚拟网络:与应用服务应用集成,并隔离后端网络流量。
  • Azure Database for PostgreSQL 灵活服务器:只能从虚拟网络内部访问。 你的数据库和用户创建于此服务器上。
  • 专用 DNS 区域:在虚拟网络中启用 PostgreSQL 服务器的 DNS 解析。

屏幕截图显示已完成的部署过程。

遇到问题? 检查故障排除部分

3.验证连接设置

创建向导已经为你生成了连接变量作为应用设置。 在此步骤中,你将了解如何查找应用设置,以及如何创建自己的应用设置。

使用应用设置可以将连接机密保留在代码存储库之外。 准备好将机密移动到更安全的位置时,可改用 Key Vault 引用

步骤 1:在左侧菜单的“应用服务”页面中,选择“环境变量”

显示如何在“应用服务”中打开配置页面的屏幕截图。

步骤 2:在“环境变量”页的“应用设置”选项卡中,验证 AZURE_POSTGRESQL_CONNECTIONSTRING 是否存在。 它在运行时作为环境变量注入。

显示如何查看自动生成的连接字符串的屏幕截图。

步骤 4:选择“添加应用程序设置”。 将设置命名为 PORT 并将其值设置为 8080,这是 Quarkus 应用程序的默认端口。 选择“应用”。

显示如何在 Azure 门户中设置 PORT 应用设置的屏幕截图。

步骤 5:依次选择“应用”、“确认”

显示如何在 Azure 门户中保存 PORT 应用设置的屏幕截图。

遇到问题? 检查故障排除部分

4.部署示例代码

在此步骤中,你将使用 GitHub Actions 配置 GitHub 部署。 这只是部署到应用服务的许多方法之一,也是一种在部署过程中持续集成的好方法。 默认情况下,GitHub 存储库的每个 git push 都会启动生成和部署操作。

注意以下事项:

  • 部署的 Java 包必须是 Uber-Jar
  • 为简化教程,在部署过程中禁用测试。 GitHub Actions 运行程序无权访问 Azure 中的 PostgreSQL 数据库,因此需要数据库访问权限的任何集成测试都将失败(Quarkus 示例应用程序就是这种情况)。

步骤 1:返回“应用服务”页,在左侧菜单中,选择“部署中心”

显示如何在“应用服务”中打开部署中心的屏幕截图。

步骤 2:在“部署中心”页中:

  1. 在“源”中,选择“GitHub”。 默认情况下,选择 GitHub Actions 作为生成提供程序。
  2. 登录到 GitHub 帐户,并按照提示授权 Azure。
  3. 在“组织”中,选择你的帐户。
  4. 在“存储库”中,选择“msdocs-quarkus-postgresql-sample-app”
  5. 在“分支”中,选择“starter-no-infra”。
  6. 在“身份验证类型”中,选择“用户分配的标识(预览版)”
  7. 在顶部菜单中,选择“保存”。 应用服务会将工作流文件提交到所选 GitHub 存储库中(在 .github/workflows 目录中)。

显示如何使用 GitHub Actions 配置 CI/CD 的屏幕截图。

步骤 3:返回示例分支的 GitHub codespace,运行 git pull origin starter-no-infra。 这会将新提交的工作流文件拉取到 codespace。

显示 GitHub codespace 内的 git 拉取的屏幕截图。

步骤 4:

  1. 在资源管理器中打开 src/main/resources/application.properties。 Quarkus 使用此文件加载 Java 属性。
  2. 找到注释的代码(第 10-11 行),并取消注释。 此代码将生产变量 %prod.quarkus.datasource.jdbc.url 设置为创建向导的应用设置。 quarkus.package.type 设置为生成 Uber-Jar,需要在应用服务中运行。

显示 GitHub codespace 和已打开的 application.properties 文件的屏幕截图。

步骤 5:

  1. 在资源管理器中打开 .github/workflows/main_msdocs-quarkus-postgres-XYZ.yml。 此文件由应用服务创建向导创建。
  2. Build with Maven 步骤下,将 Maven 命令更改为 mvn clean install -DskipTests-DskipTests 跳过 Quarkus 项目中的测试,以避免 GitHub 工作流过早失败。

显示 GitHub codespace 和打开的 GitHub 工作流 YAML 的屏幕截图。

步骤 6:

  1. 选择“源代码管理”扩展。
  2. 在文本框中,键入类似 Configure DB and deployment workflow 的提交消息。
  3. 选择“提交”,然后使用“是”进行确认
  4. 选择“同步更改 1”,然后使用“确定”进行确认。

显示正在提交并推送到 GitHub 的更改的屏幕截图。

步骤 7:返回到 Azure 门户中的“部署中心”页:

  1. 选择“日志”。 已从提交的更改开始新的部署运行。
  2. 在部署运行的日志项中,选择具有最新时间戳的“生成/部署日志”条目。

显示如何在部署中心打开部署日志的屏幕截图。

步骤 8:你已转到 GitHub 存储库,并看到 GitHub Action 正在运行。 工作流文件定义两个单独的阶段,即生成和部署阶段。 等待 GitHub 运行以显示“完成”状态。 此过程大约需要 5 分钟。

屏幕截图显示 GitHub 正在运行。

遇到问题? 检查故障排除部分

5.浏览到应用

步骤 1:在“应用服务”页中:

  1. 从左侧菜单中选择“概述”。
  2. 选择应用的 URL。 你也可以直接导航到 https://<app-name>.chinacloudsites.cn

显示如何从 Azure 门户中启动应用服务的屏幕截图。

步骤 2:向列表中添加一些水果。 恭喜,你已在 Azure 应用服务中运行了一个 Web 应用,并安全连接到了 Azure Database for PostgreSQL。

在 Azure 中运行 PostgreSQL 的 Quarkus Web 应用的屏幕截图,其中显示了水果列表。

6.流式传输诊断日志

Azure 应用服务会捕获输出到控制台的所有消息,以帮助你诊断应用程序的问题。 示例应用程序包括标准 JBoss 日志记录语句,用于演示此功能,如下所示。

    private static final Logger LOGGER = Logger.getLogger(FruitEntityResource.class.getName());

    @GET
    public List<FruitEntity> get() {
        LOGGER.info("In FruitEntityResource.get()");
        return FruitEntity.listAll(Sort.by("name"));
    }

步骤 1:在“应用服务”页中:

  1. 从左菜单中选择“应用服务日志”。
  2. 在“应用程序日志记录”下,选择“文件系统”。
  3. 在顶部菜单中,选择“保存”。

显示如何在 Azure 门户的应用服务中启用本机日志的屏幕截图。

步骤 2:在左侧菜单中,选择“日志流”。 将显示应用的日志,包括平台日志和容器内部的日志。

显示如何在 Azure 门户中查看日志流的屏幕截图。

为 .NET、Node.js、Python 和 Java 应用程序启用 Azure Monitor OpenTelemetry 系列中详细了解 Java 应用中的日志记录。

7.清理资源

完成后,可以通过删除资源组从 Azure 订阅中删除所有资源。

步骤 1:在 Azure 门户顶部的搜索栏中:

  1. 输入资源组名称。
  2. 选择前面创建的资源组。

显示如何在 Azure 门户中搜索和导航到资源组的屏幕截图。

步骤 2:在资源组页上,选择“删除资源组”。

显示 Azure 门户中“删除资源组”按钮位置的屏幕截图。

步骤 3:

  1. 键入资源组名称以确认删除。
  2. 选择“删除”。
  3. 再次使用“删除”进行确认

Azure 门户中删除资源组确认对话框的屏幕截图。 :

2.创建 Azure 资源并部署示例应用

在此步骤中,将创建 Azure 资源并将示例应用部署到 Linux 上的应用服务。 本教程中使用的步骤创建一组默认安全的资源,其中包括应用服务和 Azure Database for PostgreSQL。

开发容器已具有 Azure Developer CLI (AZD)。

  1. 从存储库根路径,运行 azd init

    azd init --template javase-app-service-postgresql-infra
    
  2. 出现提示时,请提供以下答案:

    问题 Answer
    继续在“<your-directory>”中初始化应用? Y
    你希望对这些文件执行哪些操作? 使现有文件保持不变
    输入新环境名称 键入唯一名称。 AZD 模板将此名称用作 Azure 中 Web 应用的 DNS 名称的一部分 (<app-name>.chinacloudsites.cn)。 允许使用字母数字字符和下划线。
  3. 通过运行 azd auth login 命令并按照提示登录到 Azure:

    azd auth login
    
  4. 使用 azd up 命令创建必要的 Azure 资源并部署应用代码。 按照提示为 Azure 资源选择所需的订阅和位置。

    azd up
    

    azd up 命令需要大约 15 分钟才能完成(Redis 缓存需要的时间最长)。 它还会编译和部署应用程序代码,但你稍后将修改代码以使用应用服务。 在运行时,该命令会提供有关预配和部署过程的消息,包括指向 Azure 中部署的链接。 完成后,命令还会显示指向部署应用程序的链接。

    此 AZD 模板包含使用以下 Azure 资源生成安全默认体系结构的文件(azure.yamlinfra 目录):

    • 资源组:所有已创建资源的容器。
    • 应用服务计划:为应用服务定义计算资源。 将创建 B1 层中的 Linux 计划。
    • 应用服务:表示应用并在应用服务计划中运行。
    • 虚拟网络:与应用服务应用集成,并隔离后端网络流量。
    • Azure Database for PostgreSQL 灵活服务器:只能从专用终结点后面访问。 将在服务器上为你创建数据库。
    • Azure Cache for Redis:只能从虚拟网络中访问。
    • 专用 DNS 区域:在虚拟网络中启用数据库服务器和 Redis 缓存的 DNS 解析。
    • Log Analytics 工作区:充当应用日志传送的目标容器,还可以在其中查询日志。
    • 密钥保管库:使用 AZD 重新部署时,用于保留数据库密码。

遇到问题? 检查故障排除部分

3.验证连接字符串

你使用的 AZD 模板已为你生成了连接变量作为应用设置,并将它们输出到终端,以方便你使用。 使用应用设置可以将连接机密保留在代码存储库之外。

  1. 在 AZD 输出中,找到应用设置 AZURE_POSTGRESQL_CONNECTIONSTRING。 为保护机密安全,只会显示设置名称。 它们在 AZD 输出中如下所示:

     App Service app has the following connection strings:
    
             - AZURE_POSTGRESQL_CONNECTIONSTRING
             - AZURE_REDIS_CONNECTIONSTRING
     

    AZURE_POSTGRESQL_CONNECTIONSTRING 包含 Azure 中 PostgreSQL 数据库的连接字符串。 稍后需要在代码中使用它。

  2. 为方便起见,AZD 模板会显示应用的应用设置页的直接链接。 找到该链接并在新的浏览器选项卡中打开它。稍后,将使用 AZD 而不是在门户中添加应用设置。

遇到问题? 检查故障排除部分

4.修改示例代码并重新部署

  1. 返回示例分支的 GitHub codespace,打开 infra/resources.bicep

  2. 找到 appSettings 资源并注释属性 PORT: '8080'。 完成后,appSettings 资源应如以下代码所示:

    resource appSettings 'config' = {
      name: 'appsettings'
      properties: {
        PORT: '8080'
      }
    }
    
  3. 在资源管理器中打开 src/main/resources/application.properties

  4. 找到注释的代码(第 10-11 行),并取消注释。

    %prod.quarkus.datasource.jdbc.url=${AZURE_POSTGRESQL_CONNECTIONSTRING}
    quarkus.package.type=uber-jar
    

    此代码将生产变量 %prod.quarkus.datasource.jdbc.url 设置为创建向导的应用设置。 quarkus.package.type 设置为生成 Uber-Jar,需要在应用服务中运行。

  5. 返回 codespace 终端,运行 azd up

    azd up
    

    提示

    azd up 实际上是 azd packageazd provisionazd deployazd provision 允许更新在 infra/resources.bicep 中所做的更改。 azd deploy 上传生成的 Jar 文件。

    若要了解如何打包 Jar 文件,可以单独运行 azd package --debug

遇到问题? 检查故障排除部分

5.浏览到应用

  1. 在 AZD 输出中,找到应用的 URL 并在浏览器中导航到该 URL。 该 URL 在 AZD 输出中如下所示:

     Deploying services (azd deploy)
    
       (✓) Done: Deploying service web
       - Endpoint: https://<app-name>.chinacloudsites.cn/
     
  2. 向列表中添加一些水果。

    在 Azure 中运行 PostgreSQL 的 Quarkus Web 应用的屏幕截图,其中显示了水果。

    恭喜,你已在 Azure 应用服务中运行了一个 Web 应用,并安全连接到了 Azure Database for PostgreSQL。

遇到问题? 检查故障排除部分

6.流式传输诊断日志

Azure 应用服务可以捕获控制台日志,以帮助你诊断应用程序的问题。 为方便起见,AZD 模板已启用对本地文件系统的日志记录以及将日志传送到 Log Analytics 工作区

示例应用程序包括标准 JBoss 日志记录语句,用于演示此功能,如下所示。

    private static final Logger LOGGER = Logger.getLogger(FruitEntityResource.class.getName());

    @GET
    public List<FruitEntity> get() {
        LOGGER.info("In FruitEntityResource.get()");
        return FruitEntity.listAll(Sort.by("name"));
    }

在 AZD 输出中,找到流式传输应用服务日志的链接,并在浏览器中导航到该链接。 该链接在 AZD 输出中如下所示:

Stream App Service logs at: https://portal.azure.cn/#@/resource/subscriptions/<subscription-guid>/resourceGroups/<group-name>/providers/Microsoft.Web/sites/<app-name>/logStream

为 .NET、Node.js、Python 和 Java 应用程序启用 Azure Monitor OpenTelemetry 系列中详细了解 Java 应用中的日志记录。

遇到问题? 检查故障排除部分

7.清理资源

若要删除当前部署环境中的所有 Azure 资源,请运行 azd down 并按照提示进行操作。

azd down

故障排除

我看到错误日志“错误 [org.acm.hib.orm.pan.ent.FruitEntityResource] (vert.x-eventloop-thread-0) 未能处理请求:jakarta.ws.rs.NotFoundException: 未找到 HTTP 404”。

这是一个 Vert.x 错误(请参阅 Quarkus 反应体系结构),指示客户端请求了未知路径。 每个应用启动时都会发生此错误,因为应用服务通过向 /robots933456.txt 发送 GET 请求来验证应用启动。

应用未能启动并在日志显示以下错误:“模型类是为默认持久性“<default>”单元定义的,但未找到配置的数据源“<default>”: 不会创建默认 EntityManagerFactory。

此 Quarkus 错误很可能是因为应用无法连接到 Azure 数据库所致。 确保应用设置 AZURE_POSTGRESQL_CONNECTIONSTRING 尚未更改,并且 application.properties 正确使用应用设置

常见问题

此设置花费有多大?

所创建资源的定价如下所示:

  • 应用服务计划在基本层中创建,可以进行纵向扩展或缩减。 请参阅应用服务定价
  • PostgreSQL 灵活服务器是在最低可突发层 Standard_B1ms 中创建的,该层提供最小的存储大小,但可以纵向扩展或缩减。 请参阅 Azure Database for PostgreSQL 定价
  • 除非配置额外的功能(例如对等互连),否则虚拟网络不会产生费用。 请参阅 Azure 虚拟网络定价
  • 专用 DNS 区域会产生少量费用。 请参阅 Azure DNS 定价

如何使用其他工具连接到在虚拟网络后面受保护的 PostgreSQL 服务器?

  • 要从命令行工具进行基本访问,可以从应用的 SSH 终端运行 psql
  • 若要从桌面工具进行连接,计算机必须位于虚拟网络中。 例如,它可以是其中某个子网中的 Azure VM,也可以是与 Azure 虚拟网络建立站点到站点 VPN 连接的本地网络中的计算机。

本地应用开发如何与 GitHub Actions 配合使用?

以应用服务中自动生成的工作流文件为例,每个 git push 都会启动新的生成和部署运行。 从 GitHub 存储库的本地克隆中,进行所需更新并推送到 GitHub。 例如:

git add .
git commit -m "<some-message>"
git push origin main

如果想要在 GitHub 工作流中使用 PostgreSQL 运行测试,该怎么办?

默认 Quarkus 示例应用程序包括数据库连接性测试。 为避免连接错误,添加了 -skipTests 属性。 如果需要,可针对 PostgreSQL 服务容器运行测试。 例如,在 GitHub 分支中自动生成的工作流文件 (.github/workflows/main_cephalin-quarkus.yml) 中,进行以下更改:

  1. 将 PostgreSQL 容器的 YAML 代码添加到 build 作业,如以下代码片段所示。

    ...
    jobs:
      build:
        runs-on: ubuntu-latest
    
        # BEGIN CODE ADDITION
        container: ubuntu
        services:
          # Hostname for the PostgreSQL container
          postgresdb:
            image: postgres
            env:
              POSTGRES_PASSWORD: postgres
              POSTGRES_USER: postgres
              POSTGRES_DB: postgres
            # Set health checks to wait until postgres has started
            options: >-
              --health-cmd pg_isready
              --health-interval 10s
              --health-timeout 5s
              --health-retries 5
    
        # END CODE ADDITION
    
        steps:
          - uses: actions/checkout@v4
          ...
    

    container: ubuntu 告知 GitHub 在容器中运行 build 作业。 这样,开发环境 jdbc:postgresql://postgresdb:5432/postgres 中的连接字符串在工作流运行时可按原样工作。 有关 GitHub Actions 中的 PostgreSQL 连接的详细信息,请参阅创建 PostgreSQL 服务容器

  2. Build with Maven 步骤中,删除 -DskipTests。 例如:

          - name: Build with Maven
            run: mvn clean install
    

后续步骤

在开发人员指南中详细了解在应用服务上运行 Java 应用。

了解如何使用自定义域和证书保护应用。