8.3.2 部署到 Heroku
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
}
现在我们的应用程序已经部署到云上,可以接受世界各地的请求了!
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论