返回介绍

8.3.2 部署到 Heroku

发布于 2025-04-21 21:10:12 字数 4698 浏览 0 评论 0 收藏

Heroku 在应用程序部署上有一套独特的方法,不用部署完整的部署产物。Heroku 为你的应用程序安排了一个 Git 仓库。每当你向仓库里提交代码时,它都会自动为你构建并部署应用程序。

如果还是解决不了问题,则需要先将项目目录初始化为 Git 仓库。

$ git init

这样 Heroku 的命令行工具就能自动把远程 Heroku Git 仓库添加到项目里。

现在可以通过 Heroku 的命令行工具在 Heroku 中设置应用程序了。这里使用 apps:create 命令。

$ heroku apps:create sbia-readinglist

这里我要求 Heroku 将应用程序命名为 sbia-readinglist。这将成为 Git 仓库的名字,同时也是应用程序在 herokuapps.com 的子域名。你需要确定这个名字唯一,因为不能有同名应用程序。此外,也可以让 Heroku 替你生成一个独特的名字(比如 fierce-river-8120 或 serene-anchorage-6223)。

apps:create 命令会在 https://git.heroku.com/sbia-readinglist.git 创建一个远程 Git 仓库,并在本地项目的 Git 配置里添加一个名为 heroku 的远程仓库引用。这样就能通过 git 命令将项目推送到 Heroku 了。

Heroku 里的项目已经设置完毕,但我们现在还不能进行推送。Heroku 需要你提供一个名为 Procfile 的文件,告诉 Heroku 应用程序构建后该如何运行。对于阅读列表应用程序而言,我们需要告诉 Heroku,构建生成的 WAR 文件要当作可执行 JAR 文件来运行,这里使用 java 命令。1 假设应用程序是用 Gradle 来构建的,只需要如下一行内容的 Procfile:

1 当前使用的项目会实际生成一个可执行的 WAR 文件。但对 Heroku 来说,它和可执行的 JAR 文件没什么区别。

web: java -Dserver.port=$PORT -jar build/libs/readinglist.war

另一方面,如果你使用 Maven 来构建项目,JAR 文件的路径就会有所不同。Heroku 需要到 target 目录,而不是 build/libs 目录里寻找可执行 WAR 文件。具体如下:

web: java -Dserver.port=$PORT -jar target/readinglist.war

不管何种情况,你都需要像例子中那样设置 server.port 属性。这样内嵌的 Tomcat 服务器才能在 Heroku 分配的端口上(通过 $PORT 变量指定)启动。

我们差不多可以把应用程序推上 Heroku 了,但 Gradle 构建说明还要稍作调整。Heroku 构建应用程序时,会执行一个名为 stage 的任务,因此需要在 build.gradle 里添加这个 stage 任务。

task stage(dependsOn: ['build']) {
}

如你所见,这个 stage 任务什么也没做,但依赖了 build 任务。于是,在 Heroku 使用 stage 任务构建应用程序会触发 build 任务,生成的 JAR 文件会放在 build/libs 目录里。

你还需要告诉 Heroku 用什么 Java 版本来构建并运行应用程序。这样 Heroku 才能用合适的版本来运行它。最简单的方法是在项目根目录里创一个名为 system.properties 的文件,在其中设置 java.runtime.version 属性:

java.runtime.version=1.7

现在就可以将项目推上 Heroku 了。和前面说一样,只需将代码推到远程 Git 仓库,Heroku 会帮我们搞定其他事情。

$ git commit -am "Initial commit"
$ git push heroku master

然后,Heroku 会根据找到的构建说明文件,使用 Maven 或 Gradle 进行构建,再用 Procfile 里的指令来运行应用程序。就绪后,你可以用浏览器打开 http://{app name}.herokuapp.com,这里的{app name}就是你在 apps:create 里给应用程序起的名字。例如,我在部署时将应用程序命名为 sbia-readinglist,所以它的 URL 就是 http://sbia-readinglist.herokuapps.com

你可以在应用程序里随便点点,但要访问一下/health 端点。 db.database 属性会告诉你应用程序正在使用内嵌的 H2 数据库。我们应该把它换成 PostgreSQL 服务。

我们可以通过 Heroku 命令行工具的 addons:add 命令创建并绑定一个 PostgreSQL 服务。

$ heroku addons:add heroku-postgresql:hobby-dev

这里我们要使用名为 heroku-postgresql 的附加服务。这是 Heroku 提供的 PostgreSQL 服务。我们还要求使用该服务的 hobby-dev 计划,这是免费的。

在 PostgreSQL 服务创建并绑定到应用程序后,Heroku 会自动重启应用程序以保证绑定生效。但即便如此,我们在访问/health 端点时仍然会看到应用程序还在使用内嵌的 H2 数据库。那是因为 H2 的自动配置仍然有效,谁也没告诉 Spring Boot 要用 PostgreSQL 代替 H2。

一个办法是设置 spring.datasource.* 属性,做法和我们将应用程序部署到应用服务器上时一样。我们所需要的信息能在数据库服务的仪表板上找到,可以用 addons:open 命令打开仪表板。

$ heroku addons:open waking-carefully-3728

在这个例子里,数据库实例的名字是 waking-carefully-3728。该命令会在 Web 浏览器里打开仪表板页面,其中包含了你所需要的全部连接信息,包括主机名、数据库名和账户信息。总之,设置 spring.datasource.* 属性所需的一切信息都在这里了。

还有一个更简单的办法,与其自己查找那些信息,再设置到属性里,为什么不让 Spring 替我们查找信息呢?实际上,这就是 Spring Cloud Connectors 的用途。它可以用在 Cloud Foundry 和 Heroku 上,查找绑定到应用程序上的所有服务,并自动配置应用程序,以便使用那些服务。

我们只需在项目中加入 Spring Cloud Connectors 依赖即可。在 Gradle 项目里,在 build.gradle 中添加如下内容:

compile(
      "org.springframework.boot:spring-boot-starter-cloud-connectors")

如果你用的是 Maven,则添加如下 Spring Cloud Connectors <dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-cloud-connectors</artifactId>
</dependency>

只有激活 cloud Profile,Spring Cloud Connectors 才会工作。要在 Heroku 里激活 cloud Profile,可以使用 config:set 命令:

$ heroku config:set SPRING_PROFILES_ACTIVE="cloud"

现在项目里有了 Spring Cloud Connectors 依赖, cloud Profile 也激活了。我们可以再推一次应用程序。

$ git commit -am "Add cloud connector"
$ git push heroku master

应用程序启动后,登入应用程序,查看/health 端点。它应该显示应用程序已经连接到了 PostgreSQL 数据库:

"db": {
  "status": "UP",
  "database": "PostgreSQL",
  "hello": 1
}

现在我们的应用程序已经部署到云上,可以接受世界各地的请求了!

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。