使用 Heroku 的 Quarkus 数据源

Posted

技术标签:

【中文标题】使用 Heroku 的 Quarkus 数据源【英文标题】:Quarkus datasource with Heroku 【发布时间】:2020-07-15 11:18:55 【问题描述】:

我正在尝试在 Heroku 上部署我的 Quarkus 应用。它工作正常,但我需要用固定值指定数据源参数。因为 Heroku 可能会旋转这个参数,所以这不是一个好主意。

在 Quarkus 中,我需要 application.properties 中的这 3 个参数:

quarkus.datasource.username
quarkus.datasource.password
quarkus.datasource.jdbc.url

Heroku 只给了我 1 个环境变量 (DATABASE_URL),它以下列方式定义了一个连接字符串: postgres://user:pass@server:port/db-name

我知道我可以像这样使用环境变量: quarkus.datasource.jdbc.url = jdbc:$DATABASE_URL

但我需要拆分变量以提取用户和密码并更改前缀(postgresql 而不是 postgres)。

有人知道如何实现这一目标吗?

【问题讨论】:

嗨@simon-wick,您的问题解决了吗?如果是,请告诉我怎么做。 【参考方案1】:

您可以将JDBC_DATABASE_URLJDBC_DATABASE_USERNAMEJDBC_DATABASE_PASSWORD 环境变量用于您的用例。

更多详情,你可以在这里找到文档:https://devcenter.heroku.com/articles/connecting-to-relational-databases-on-heroku-with-java#using-the-jdbc_database_url

【讨论】:

来自文档:The official Heroku buildpacks for Java, Scala, Clojure, and Gradle will attempt to create a JDBC_DATABASE_URL environment variable when a dyno starts up. 我将 quarkus 原生应用程序(docker 镜像)部署到 heroku,我可以强制 heroku 添加 JDBC_DATABASE_USERNAMEJDBC_DATABASE_PASSWORD 变量吗? @tostao 遗憾的是,您不能这样做。 Heroku 在 dyno 启动时使用脚本添加这些 JDBC 环境变量。我们使用我们的官方 JVM 构建包将该脚本打包到您的 slug(图像)中。但是,由于这些构建包是开源的,您可以获取脚本并在自定义 docker 映像中使用它:github.com/heroku/heroku-buildpack-jvm-common/blob/… 我明白了你的意思:我需要安装这个heroku-buildpack-jvm 并且它会工作吗?或者我应该将这个jdbc.sh 脚本添加到我的部署工作中吗?任何示例将不胜感激。【参考方案2】:

我创建了一个 bash 脚本来从 Heroku DATABASE_URL 中提取三个 Quarkus 参数。

它适用于 JVM 和本机版本。

我的application.properties

quarkus.datasource.jdbc.url=$DB_JDBC_URL:jdbc-url
quarkus.datasource.username=$DB_JDBC_USER:postgres
quarkus.datasource.password=$DB_JDBC_PASSWORD:postgres

短版

# cut the DATABASE_URL after '@'
export DB_JDBC_URL=jdbc:postgresql://$DATABASE_URL#*@

# substring the DATABASE_URL between '//' and ':'
export DB_JDBC_USER=$(expr $DATABASE_URL : '.*/\([^:]*\):.*')

# substring the DATABASE_URL between ':' and '@'
export DB_JDBC_PASSWORD=$(expr $DATABASE_URL : '.*:\([^@]*\)@.*')

长版

Bash 脚本

使用heroku.sh 文件名将以下脚本保存在项目的根文件夹中。

#!/bin/sh
# =============================================================================
# This script automatically splits the Heroku ENV DATABASE_URL variable
# into the three JDBC variables needed from Quarkus.
# 
# It will only do the split if the DB_HEROKU_SPLIT is set to "true".
#
# If you set DB_HEROKU_SPLIT to 'false', you must pass the Quarkus parameters:
#   - DB_JDBC_URL;
#   - DB_JDBC_USER;
#   - DB_JDBC_PASSWORD.
# 
# For test purposes, you can set the DB_ECHO_VALUES to 'true' and check if the
# values are correct.
# 
# Pattern of DATABASE_URL from Heroku:
# --------------------------------------
#   postgres://username:password@host:port/databasename
# 
# Pattern of JDBC variables of Quarkus:
# -------------------------------------
#   quarkus.datasource.jdbc.url=jdbc:postgresql://host:port/databasename
#   quarkus.datasource.username=username
#   quarkus.datasource.password=password
# 
# =============================================================================

echo DB_HEROKU_SPLIT=[$DB_HEROKU_SPLIT] 

# check for 'true' in string (case insensitive)
if [[ "$DB_HEROKU_SPLIT,," == "true" ]]; then

  # cut the DATABASE_URL after '@'
  export DB_JDBC_URL=jdbc:postgresql://$DATABASE_URL#*@

  # substring the DATABASE_URL between '//' and ':'
  export DB_JDBC_USER=$(expr $DATABASE_URL : '.*/\([^:]*\):.*')

  # substring the DATABASE_URL between ':' and '@'
  export DB_JDBC_PASSWORD=$(expr $DATABASE_URL : '.*:\([^@]*\)@.*')

fi

# check for 'true' in string (case insensitive)
if [[ "$DB_ECHO_VALUES,," == "true" ]]; then

  echo DATABASE_URL=[$DATABASE_URL]
  echo DB_JDBC_URL=[$DB_JDBC_URL]
  echo DB_JDBC_USER=[$DB_JDBC_USER] 
  echo DB_JDBC_PASSWORD=[$DB_JDBC_PASSWORD]

fi

Dockerignore

记得将此文件包含在您的.dockerignore中:

*
!heroku.sh
!target/*-runner
!target/*-runner.jar
!target/lib/*
!target/quarkus-app/*

Dockerfile.jvm

用这个替换原来的ENTRYPOINT

# commands from original Quarkus Dockerfile.jvm file suppressed for breviety

COPY --chown=1001 heroku.sh /deployments/heroku.sh
RUN chmod 540 /deployments/heroku.sh

CMD [ "/bin/bash", "-c" , ". /deployments/heroku.sh && /deployments/run-java.sh" ]

Dockerfile.native

用这个替换原来的CMD

# commands from original Quarkus Dockerfile.jvm file suppressed for breviety

COPY --chown=1001 heroku.sh /work/heroku.sh
RUN chmod 540 /work/heroku.sh

CMD ["/bin/bash", "-c", ". ./heroku.sh && ./application", "-Dquarkus.http.host=0.0.0.0"]

Heroku 配置变量

DB_HEROKU_SPLIT

如果您希望 bash 脚本为您提取 Quarkus 数据源变量,请将 DB_HEROKU_SPLIT 添加到 Heroku 的 Config Vars 并将其设置为 true

将其设置为false,您可以在 Heroku Config Vars 中创建 Quarkus 数据源(DB_JDBC_URL、、DB_JDBC_PASSWORD 和 DB_JDBC_PASSWORD),并绕过 bash 脚本直接将它们传递给 Quarkus。

DB_ECHO_VALUES

我还创建了一个DB_ECHO_VALUES 变量,允许您在日志中显示数据源。如果要在屏幕上打印日志,只需将DB_ECHO_VALUES 设置为true即可。

【讨论】:

以上是关于使用 Heroku 的 Quarkus 数据源的主要内容,如果未能解决你的问题,请参考以下文章

尝试使用 Quarkus 从本地 H2 数据库中检索所有行

在测试我的 Quarkus 应用程序时如何使用内存中的 H2 数据库?

Quarkus 找不到内容类型多部分/表单数据休息客户端的编写器

为啥“Quarkus”选择“Agroal”而不是“HikariCP”作为首选数据源和连接池实现? [关闭]

在 quarkus 上使用 panache 执行自定义 JPQL 查询

quarkus数据库篇之一:比官方demo更简单的基础操作