8.3.1 部署到 Cloud Foundry
Cloud Foundry 是 Pivotal 的 PaaS 平台。这家公司也赞助了 Spring Framework 和 Spring 平台里的其他库。Cloud Foundry 里最吸引人的特点之一就是它既有开源版本,也有多个商业版本。你可以选择在何处运行 Cloud Foundry。它甚至还可以在公司数据中心的防火墙后运行,提供私有云。
我打算将阅读列表应用程序部署到 Pivotal Web Services(PWS)上。这是一个由 Pivotal 托管的公共 Cloud Foundry,地址是 http://run.pivotal.io 。如果想使用 PWS,你可以注册一个账号。PWS 提供为期 60 天的免费试用,在试用期间无需提交任何信用卡信息。
在注册了 PWS 后,可以从 https://console.run.pivotal.io/tools 下载并安装 cf
命令行工具。你可以通过这个工具将应用程序推上 Cloud Foundry。但你要先用这个工具登录自己的 PWS 账号。
$ cf login -a https://api.run.pivotal.io
API endpoint: https://api.run.pivotal.io
Email> {your email}
Password> {your password}
Authenticating...
OK
现在我们已经可以把阅读列表应用程序传到云上了。实际上,我们的项目已经做好了部署到 Cloud Foundry 的准备,只需使用 cf push
命令把它推上去就好。
$ cf push sbia-readinglist -p build/libs/readinglist.war
cf push
命令的第一个参数指定了应用程序在 Cloud Foundry 里的名称。这个名称将被用作托管应用程序的子域名。本例中,应用程序的完整域名将是 http://sbia-readinglist.cfapps.io 。因此,应用程序的命名很重要。名字必须独一无二,这样才不会和 Cloud Foundry 里部署的其他应用程序(包括其他用户部署的应用程序)发生冲突。
因为空想一个独一无二的名称有点困难,所以 cf push
命令提供了一个 --random-route
选项,可以为你随机产生一个子域名。下面的例子演示了如何上传阅读列表应用程序,生成一个随机的子域名。
$ cf push sbia-readinglist -p build/libs/readinglist.war --random-route
在使用了 --random-route
后,还是要设定应用程序名称。会有两个随机选择的单词添加到后面,组成子域名。(在我自己尝试的时候,生成的子域名是 sbia-readinglist-gastroenterologicalstethoscope。)
不仅仅是 WAR 文件 虽然我们部署的应用程序是一个 WAR 文件,但 Cloud Foundry 也可以部署其他格式的 Spring Boot 应用程序,包括可执行的 JAR 文件,甚至 Spring Boot CLI 开发的未经编译的 Groovy 脚本。
如果一切顺利,我们部署的应用程序应该可以处理请求了。假设子域名是 sbia-readinglist,你可以用浏览器访问 http://sbia-readinglist.cfapps.io ,看看效果。你应该会被引导到登录页。回想一下,数据库迁移脚本中插入了一个名为 craig 的用户,密码是 password,可以以此登录应用程序。
你可以在应用程序里随便点点,加几本书。所有的东西都可以运行,但还是有点不对劲。如果重启应用程序(通过 cf restart
命令),重新登录,你会发现阅读列表清空了。你在重启前添加的书都不见了。
应用程序重启后数据消失,原因在于我们还在使用内嵌的 H2 数据库。我们可以通过 Actuator 的/health 端点验证推测。它返回的信息大约是这样的:
{
"status": "UP",
"diskSpace": {
"status": "UP",
"free": 834236510208,
"threshold": 10485760
},
"db": {
"status": "UP",
"database": "H2",
"hello": 1
}
}
请注意 db.database
属性的值。它证实了我们之前的怀疑 - 果然用的是内嵌的 H2 数据库。我们需要修复这个问题。
实际上,Cloud Foundry 以市集服务(marketplace services)的形式提供了一些数据库以供选择,包括 MySQL 和 PostgreSQL。因为我们已经在项目里放了 PostgreSQL 的 JDBC 驱动,所以就使用市集里的 PostgreSQL 服务,名字是 elephantsql。
elephantsql 服务也有不少计划可选,小到开发用的小型数据库,大到工业级生产数据库。elephantsql 的完整计划列表可以通过 cf marketplace
命令获得。
$ cf marketplace -s elephantsql
Getting service plan information for service elephantsql as craig@habuma.com...
OK
service plan description free or paid
turtle Tiny Turtle free
panda Pretty Panda paid
hippo Happy Hippo paid
elephant Enormous Elephant paid
如你所见,比较严谨的生产级数据库计划都是要付费的。你可以选择你所期望的计划。我先假设你会选择免费的 turtle。
创建数据库服务的实例,需要使用 cf create-service
命令,指定服务名、计划名和实例名。
$ cf create-service elephantsql turtle readinglistdb
Creating service readinglistdb in org habuma /
space development as craig@habuma.com...
OK
服务创建后,需要通过 cf bind-service
命令将它绑定到我们的应用程序上。
$ cf bind-service sbia-readinglist readinglistdb
将一个服务绑定到应用程序上不过就是为应用程序提供了连接服务的细节,这里用的是名为 VCAP_SERVICES
的环境变量。它不会通过修改应用程序来使用服务。
我们可以改写阅读列表应用程序,读取 VCAP_SERVICES
,使用其中提供的信息来连接数据库服务。但其实完全不用这么做。实际上,我们只需用 cf restage
命令重启应用程序就可以了:
$ cf restage sbia-readinglist
cf restage
命令会让 Cloud Foundry 重新部署应用程序,并重新计算 VCAP_SERVICES
的值。如此一来,我们的应用程序会在 Spring 应用程序上下文里声明一个引用了绑定数据库服务的 DataSource
Bean,用它来替换原来的 DataSource
Bean。这样我们就能抛开内嵌的 H2 数据库,使用 elephantsql 提供的 PostgreSQL 服务了。
现在来试一下。登录应用程序,添加几本书,然后重启。重启之后你所添加的书应该还在列表里,因为它们已经被持久化在绑定的数据库服务里,而非内嵌的 H2 数据库里。再访问一下 Actuator 的/health 端点,返回的内容能证明我们在使用 PostgreSQL:
{
"status": "UP",
"diskSpace": {
"status": "UP",
"free": 834331525120,
"threshold": 10485760
},
"db": {
"status": "UP",
"database": "PostgreSQL",
"hello": 1
}
}
Cloud Foundry 对 Spring Boot 应用程序部署而言是极佳的 PaaS,Cloud Foundry 与 Spring 项目搭配可谓如虎添翼。但 Cloud Foundry 并非 Spring Boot 应用程序在 PaaS 方面的唯一选择。让我们来看看如何将阅读列表应用程序部署到另一个流行的 Paas 平台:Heroku。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论