第六部分,部署Spring Boot应用程序
Spring Boot的灵活打包选项在部署应用程序时提供了大量选择。您可以轻松地将Spring Boot应用程序部署到各种云平台,容器映像(如Docker)或虚拟/真实机器。
本节介绍一些更常见的部署方案。
58.部署到云
Spring Boot的可执行文件夹是为大多数流行的云PaaS(平台即服务)提供商准备的。这些提供者往往要求你“携带你自己的容器”; 他们管理应用程序进程(特别是不是Java应用程序),因此他们需要一些中间层,使您的应用程序 适应云对正在运行的进程的看法。
两个流行的云提供商Heroku和Cloud Foundry采用“构建包”的方式。buildpack将您部署的代码封装在启动应用程序所需的任何代码中:它可能是一个JDK和一个调用java
,它可能是一个嵌入式Web服务器,或者它可能是一个完整的应用程序服务器。buildpack是可插入的,但理想情况下,您应该能够尽可能少地进行自定义。这减少了不受您控制的功能的占用空间。它最大限度地减少了开发和生产环境之间的差异。
理想情况下,您的应用程序就像Spring Boot可执行程序jar一样,具有打包的所有内容。
在本节中,我们将看看如何获得我们在“入门”部分开发并在云中运行的 简单应用程序。
58.1 Cloud Foundry
如果没有指定其他buildpack,Cloud Foundry会提供默认构建包。Cloud Foundry Java buildpack 对Spring应用程序(包括Spring Boot)提供了出色的支持。您可以部署独立的可执行jar应用程序以及传统的.war
打包应用程序。
一旦构建了应用程序(例如使用mvn clean package
)并 安装了cf
命令行工具,只需使用以下cf push
命令部署应用程序,将路径替换为已编译的应用程序.jar
。确保 在推送应用程序之前使用cf
命令行客户端登录 。
$ cf push acloudyspringtime -p target/demo-0.0.1-SNAPSHOT.jar
有关更多选项,请参阅cf push
文档。如果manifest.yml
在同一目录中存在Cloud Foundry 文件,将会查询它。
在这里,我们正在替代 |
此时cf
将开始上传您的应用程序:
Uploading acloudyspringtime... OK Preparing to start acloudyspringtime... OK -----> Downloaded app package (8.9M) -----> Java Buildpack source: system -----> Downloading Open JDK 1.7.0_51 from .../x86_64/openjdk-1.7.0_51.tar.gz (1.8s) Expanding Open JDK to .java-buildpack/open_jdk (1.2s) -----> Downloading Spring Auto Reconfiguration from 0.8.7 .../auto-reconfiguration-0.8.7.jar (0.1s) -----> Uploading droplet (44M) Checking status of app 'acloudyspringtime'... 0 of 1 instances running (1 starting) ... 0 of 1 instances running (1 down) ... 0 of 1 instances running (1 starting) ... 1 of 1 instances running (1 running) App started
恭喜!该应用程序现在已经生效!
然后验证部署的应用程序的状态很容易:
$ cf apps Getting applications in ... OK name requested state instances memory disk urls ... acloudyspringtime started 1/1 512M 1G acloudyspringtime.cfapps.io ...
一旦Cloud Foundry确认您的应用程序已经部署完毕,您应该能够按照给定的URI访问应用程序,在这种情况下 http://acloudyspringtime.cfapps.io/
。
58.1.1绑定到服务
默认情况下,有关正在运行的应用程序的元数据以及服务连接信息将作为环境变量(例如:)显示给应用程序 $VCAP_SERVICES
。此架构决定归功于Cloud Foundry的多语言支持(任何语言和平台均可作为buildpack支持); 过程范围的环境变量是语言不可知的。
环境变量并不总是适用于最简单的API,因此Spring Boot会自动提取它们并将数据变为可通过Spring Environment
抽象化访问的属性:
@Component class MyBean implements EnvironmentAware { private String instanceId; @Override public void setEnvironment(Environment environment) { this.instanceId = environment.getProperty("vcap.application.instance_id"); } // ... }
所有Cloud Foundry属性都以前缀vcap
。您可以使用vcap属性来访问应用程序信息(如应用程序的公用URL)和服务信息(如数据库凭证)。有关CloudFoundryVcapEnvironmentPostProcessor
完整的详细信息,请参阅Javadoc。
在春季云连接器项目是任务,如配置数据源更适合。Spring Boot包含自动配置支持和 |
58.2 Heroku
Heroku是另一个流行的PaaS平台。要定制Heroku版本,您需要提供一个 Procfile
,它提供了部署应用程序所需的咒语。Heroku port
为Java应用程序分配a 使用,然后确保到外部URI的路由工作。
您必须配置您的应用程序以侦听正确的端口。以下是Procfile
我们的入门REST应用程序:
web: java -Dserver.port=$PORT -jar target/demo-0.0.1-SNAPSHOT.jar
Spring Boot使-D
参数作为可从Spring Environment
实例访问的属性提供 。所述server.port
配置属性被馈送到嵌入的Tomcat,码头或暗流实例,它然后使用它时,它启动。$PORT
Heroku PaaS 将环境变量分配给我们。
Heroku默认使用Java 1.8。只要您的Maven或Gradle构建版本设置为使用相同版本(Maven用户可以使用java.version属性),就可以。如果您想使用JDK 1.7,请在您的pom.xml
和Procfile
名为旁边创建一个新文件system.properties
。在此文件中添加以下内容:
java.runtime.version=1.7
这应该是你需要的一切。Heroku部署最常用的工作流程是 git push
生产代码。
$ git push heroku master Initializing repository, done. Counting objects: 95, done. Delta compression using up to 8 threads. Compressing objects: 100% (78/78), done. Writing objects: 100% (95/95), 8.66 MiB | 606.00 KiB/s, done. Total 95 (delta 31), reused 0 (delta 0) -----> Java app detected -----> Installing OpenJDK 1.8... done -----> Installing Maven 3.3.1... done -----> Installing settings.xml... done -----> Executing: mvn -B -DskipTests=true clean install [INFO] Scanning for projects... Downloading: https://repo.spring.io/... Downloaded: https://repo.spring.io/... (818 B at 1.8 KB/sec) .... Downloaded: http://s3pository.heroku.com/jvm/... (152 KB at 595.3 KB/sec) [INFO] Installing /tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a8229/target/... [INFO] Installing /tmp/build_0c35a5d2-a067-4abc-a232-14b1fb7a8229/pom.xml ... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 59.358s [INFO] Finished at: Fri Mar 07 07:28:25 UTC 2014 [INFO] Final Memory: 20M/493M [INFO] ------------------------------------------------------------------------ -----> Discovering process types Procfile declares types -> web -----> Compressing... done, 70.4MB -----> Launching... done, v6 http://agile-sierra-1405.herokuapp.com/ deployed to Heroku To git@heroku.com:agile-sierra-1405.git * [new branch] master -> master
您的应用程序现在应该在Heroku上运行。
58.3 OpenShift
OpenShift是RedHat公共(和企业)PaaS解决方案。像Heroku一样,它通过运行由git提交触发的脚本来工作,因此只要Java运行时可用,您就可以以任何方式编写启动Spring Boot应用程序的脚本(这是您可以在OpenShift)。要做到这一点,你可以使用 DIY弹药筒和挂钩在你的仓库下.openshift/action_hooks
:
基本模型是:
- 确保Java和您的构建工具远程安装,例如使用
pre_build
钩子(默认安装Java和Maven,Gradle不是) -
使用
build
钩子来构建你的jar(使用Maven或Gradle),例如#!/bin/bash cd $OPENSHIFT_REPO_DIR mvn package -s .openshift/settings.xml -DskipTests=true
- 添加一个
start
调用的钩子java -jar …
#!/bin/bash cd $OPENSHIFT_REPO_DIR nohup java -jar target/*.jar --server.port=${OPENSHIFT_DIY_PORT} --server.address=${OPENSHIFT_DIY_IP} &
- 使用
stop
钩子(因为开始应该干净地返回),例如#!/bin/bash source $OPENSHIFT_CARTRIDGE_SDK_BASH PID=$(ps -ef | grep java.*\.jar | grep -v grep | awk '{ print $2 }') if [ -z "$PID" ] then client_result "Application is already stopped" else kill $PID fi
- 在平台中嵌入来自平台提供的环境变量的服务绑定
application.properties
,例如,spring.datasource.url: jdbc:mysql://${OPENSHIFT_MYSQL_DB_HOST}:${OPENSHIFT_MYSQL_DB_PORT}/${OPENSHIFT_APP_NAME} spring.datasource.username: ${OPENSHIFT_MYSQL_DB_USERNAME} spring.datasource.password: ${OPENSHIFT_MYSQL_DB_PASSWORD}
在他们的网站上有一篇关于在OpenShift上运行Gradle的博客,这将使您开始使用Gradle构建来运行应用程序。
58.4亚马逊网络服务(AWS)
亚马逊Web服务提供了多种方式来安装基于Spring Boot的应用程序,既可以作为传统的Web应用程序(war),也可以作为带有嵌入式Web服务器的可执行jar文件。选项包括:
- AWS Elastic Beanstalk
- AWS Code Deploy
- AWS OPS Works
- AWS Cloud Formation
- AWS Container Registry
每个模块都有不同的功能和定价模式,下面我们将仅介绍最简单的选项:AWS Elastic Beanstalk。
58.4.1 AWS Elastic Beanstalk
如官方Elastic Beanstalk Java指南中所述,部署Java应用程序有两个主要选项; 您可以使用“Tomcat平台”或“Java SE平台”。
使用Tomcat平台
这个选项适用于产生war文件的Spring Boot项目。没有任何特殊的配置要求,只需按照官方指南。
使用Java SE平台
此选项适用于生成jar文件并运行嵌入式Web容器的Spring Boot项目。Elastic Beanstalk环境在端口80上运行nginx实例,以代理在端口5000上运行的实际应用程序。要配置它,请将以下内容添加到您的 application.properties
:
server.port=5000
最佳实践
上传二进制文件而不是源文件
默认情况下,Elastic Beanstalk会上传源并在AWS中编译它们。要上传二进制文件,请将以下内容添加到您的.elasticbeanstalk/config.yml
文件中:
deploy: artifact: target/demo-0.0.1-SNAPSHOT.jar
通过设置环境类型来降低成本
默认情况下,Elastic Beanstalk环境负载均衡。负载平衡器具有成本透视图,为了避免这种情况,请按照Amazon文档中的描述将环境类型设置为“单实例” 。使用CLI也可以使用以下命令创建单实例环境:
eb create -s
58.4.2总结
这是获得AWS的最简单方法之一,但还有更多内容需要解决,例如:如何将Elastic Beanstalk集成到任何CI / CD工具中,使用Elastic Beanstalk maven插件而不是CLI等。博客 更详细地介绍了这些话题。
58.5 Boxfuse和亚马逊网络服务
Boxfuse通过将Spring Boot可执行jar或war转换为可以在VirtualBox或AWS上无变化部署的最小VM映像来实现。Boxfuse为Spring Boot提供了深度集成,并将使用Spring Boot配置文件中的信息自动配置端口和运行状况检查URL。Boxfuse将这些信息用于它生成的图像以及它提供的所有资源(实例,安全组,弹性负载平衡器等)。
创建Boxfuse账户后,将其连接到您的AWS账户并安装最新版本的Boxfuse客户端,您可以按如下方式将Spring Boot应用程序部署到AWS(确保应用程序由Maven或Gradle首先使用,例如mvn clean package
):
$ boxfuse run myapp-1.0.jar -env=prod
有关更多选项,请参阅boxfuse run
文档。如果当前目录中存在boxfuse.com/docs/commandline/#configuration [ boxfuse.conf
]文件,它将被咨询。
默认情况下,Boxfuse将激活 |
此时boxfuse
将为您的应用程序创建一个映像,将其上传,然后在AWS上配置并启动必要的资源:
Fusing Image for myapp-1.0.jar ... Image fused in 00:06.838s (53937 K) -> axelfontaine/myapp:1.0 Creating axelfontaine/myapp ... Pushing axelfontaine/myapp:1.0 ... Verifying axelfontaine/myapp:1.0 ... Creating Elastic IP ... Mapping myapp-axelfontaine.boxfuse.io to 52.28.233.167 ... Waiting for AWS to create an AMI for axelfontaine/myapp:1.0 in eu-central-1 (this may take up to 50 seconds) ... AMI created in 00:23.557s -> ami-d23f38cf Creating security group boxfuse-sg_axelfontaine/myapp:1.0 ... Launching t2.micro instance of axelfontaine/myapp:1.0 (ami-d23f38cf) in eu-central-1 ... Instance launched in 00:30.306s -> i-92ef9f53 Waiting for AWS to boot Instance i-92ef9f53 and Payload to start at http://52.28.235.61/ ... Payload started in 00:29.266s -> http://52.28.235.61/ Remapping Elastic IP 52.28.233.167 to i-92ef9f53 ... Waiting 15s for AWS to complete Elastic IP Zero Downtime transition ... Deployment completed successfully. axelfontaine/myapp:1.0 is up and running at http://myapp-axelfontaine.boxfuse.io/
您的应用程序现在应该在AWS上运行。
有一篇关于在EC2上部署Spring Boot应用的博客,以及他们网站上Boxfuse Spring Boot集成的文档,这将使您开始使用Maven构建来运行该应用。
58.6 Google Cloud
Google Cloud有几个可用于启动Spring Boot应用程序的选项。最容易入门的可能是App Engine,但您也可以找到在容器中使用Container Engine或在使用Compute Engine的虚拟机上运行Spring Boot的方法。
要在App Engine中运行,您可以先在用户界面中创建一个项目,为您设置唯一的标识符以及HTTP路由。将Java应用程序添加到项目并将其保留为空,然后使用Google Cloud SDK将Spring Boot应用程序从命令行或CI构建推入该插槽。
App Engine需要您创建一个app.yaml
文件来描述您的应用所需的资源。通常你把src/main/appengine
它放进去,看起来像这样:
service: default runtime: java env: flex runtime_config: jdk: openjdk8 handlers: - url: /.* script: this field is required, but ignored manual_scaling: instances: 1 health_check: enable_health_check: False env_variables: ENCRYPT_KEY: your_encryption_key_here
例如,您可以通过将Maven插件添加到构建配置来部署应用程序:
<plugin> <groupId>com.google.cloud.tools</groupId> <artifactId>appengine-maven-plugin</artifactId> <version>1.3.0</version> <configuration> <project>myproject</project> </configuration> </plugin>
然后部署mvn appengine:deploy
(如果您需要首先进行身份验证,构建将失败)。
Google App Engine Classic绑定到Servlet 2.5 API,所以你不能在没有修改的情况下部署Spring应用程序。请参阅本指南的 Servlet 2.5部分。 |
59.安装Spring Boot应用程序
除了使用Spring Boot应用程序外java -jar
,还可以为Unix系统创建完全可执行的应用程序。完全可执行的jar可以像任何其他可执行的二进制文件一样执行,也可以使用init.d
or 注册systemd
。这使得在普通生产环境中安装和管理Spring Boot应用程序变得非常简单。
通过在文件的前面嵌入一个额外的脚本,完全可执行的jar工作。目前,有些工具不接受这种格式,因此您可能无法始终使用此技术。例如, |
要使用Maven创建一个“完全可执行的”jar,请使用以下插件配置:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <executable>true</executable> </configuration> </plugin>
通过Gradle,等效的配置是:
springBoot { executable = true }
然后,您可以通过键入./my-application.jar
(其中 my-application
是工件的名称)来运行应用程序。包含该jar的目录将被用作应用程序的工作目录。
59.1支持的操作系统
默认脚本支持大多数Linux发行版,并在CentOS和Ubuntu上进行测试。其他平台,如OS X和FreeBSD,将需要使用自定义 embeddedLaunchScript
。
59.2 Unix / Linux服务
春天启动的应用程序可以作为Unix / Linux上使用的服务既轻松启动init.d
或systemd
。
59.2.1作为init.d服务安装(System V)
如果您已经配置了Spring Boot的Maven或Gradle插件来生成 完全可执行的jar,并且您没有使用自定义 embeddedLaunchScript
,那么您的应用程序可以用作init.d
服务。简单符号链接罐子init.d
,支持标准start
,stop
,restart
和 status
命令。
该脚本支持以下功能:
- 以拥有该jar文件的用户身份启动服务
- 跟踪应用程序的PID使用
/var/run/<appname>/<appname>.pid
- 将控制台日志写入
/var/log/<appname>.log
假设您安装了Spring Boot应用程序/var/myapp
,要将Spring Boot应用程序作为init.d
服务安装,只需创建一个符号链接:
$ sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp
安装后,您可以按照通常的方式启动和停止服务。例如,在基于Debian的系统上:
$ service myapp start
如果您的应用程序无法启动,请检查写入 |
您还可以将应用程序标记为使用标准操作系统工具自动启动。例如,在Debian上:
$ update-rc.d myapp默认值<priority>
保护一个init.d服务
以下是关于如何保护作为init.d服务运行的Spring Boot应用程序的一组准则。它并不打算成为一个应用程序及其运行环境的完整列表。 |
以root用户身份执行时,与使用root用于启动init.d服务的情况相同,缺省可执行脚本将以拥有该jar文件的用户身份运行该应用程序。你永远不应该运行Spring Boot应用程序,root
因为你的应用程序的jar文件不应该由root拥有。相反,创建一个特定的用户来运行你的应用程序并使用chown
它来使它成为jar文件的所有者。例如:
$ chown bootapp:bootapp your-app.jar
在这种情况下,默认的可执行脚本将以bootapp
用户身份运行应用程序。
为了减少应用程序用户帐户受到攻击的可能性,您应该考虑防止它使用登录shell。 |
您还应该采取措施来防止修改应用程序的jar文件。首先,配置其权限,使其不能被写入,只能由其所有者读取或执行:
$ chmod 500 your-app.jar
其次,如果您的应用程序或运行该应用程序的帐户遭到入侵,您还应该采取措施来限制损害。如果攻击者获得访问权限,他们可以将jar文件写入并更改其内容。防止这种情况的一种方法是使用chattr
以下方法使其不可变:
$ sudo chattr +i your-app.jar
这将阻止包括root在内的任何用户修改jar。
如果root用于控制应用程序的服务,并 使用.conf
文件来定制其启动,则该.conf
文件将由root用户读取和评估。它应该得到相应的保证。使用chmod
以便文件只能由所有者读取并用于 chown
使所有者成为root用户:
$ chmod 400 your-app.conf $ sudo chown root:root your-app.conf
59.2.2作为systemd服务安装
Systemd是System V init系统的继承者,现在已被许多现代Linux发行版使用。尽管您可以继续使用init.d
脚本systemd
,但也可以使用systemd
“服务”脚本启动Spring Boot应用程序。
假设您已安装Spring Boot应用程序/var/myapp
,要将Spring Boot应用程序作为systemd
服务安装,请myapp.service
使用以下示例创建一个名为脚本的脚本,并将其放置在/etc/systemd/system
目录中:
[Unit] Description=myapp After=syslog.target [Service] User=myapp ExecStart=/var/myapp/myapp.jar SuccessExitStatus=143 [Install] WantedBy=multi-user.target
记住要改变 |
请注意,该 |
请注意,与作为init.d
服务运行时不同,运行应用程序,PID文件和控制台日志文件的用户是由其systemd
自身管理的,因此必须使用“服务”脚本中的相应字段进行配置。有关更多详细信息,请参阅 服务单位配置手册页。
要将应用程序标记为在系统引导时自动启动,请使用以下命令:
$ systemctl enable myapp.service
参考man systemctl
更多细节。
59.2.3自定义启动脚本
由Maven或Gradle插件编写的默认嵌入式启动脚本可以通过多种方式进行自定义。对于大多数人来说,使用默认脚本以及一些自定义功能通常就足够了。如果你发现你不能自定义你需要的东西,你总是可以使用该embeddedLaunchScript
选项完全编写自己的文件。
写入脚本时进行自定义
在写入jar文件时,定制启动脚本的元素通常是有意义的。例如,init.d脚本可以提供一个“描述”,并且由于您事先知道这一点(并且它不会改变),所以您可以在生成jar时提供它。
要定制书写元素,请使用embeddedLaunchScriptProperties
Spring Boot Maven或Gradle插件的选项。
默认脚本支持以下属性替换:
Name | Description |
---|---|
| The script mode. Defaults to |
| The |
| The |
| The |
| The |
| The |
| The |
| The |
| The |
| The default value for |
| The default value for |
| The default value for |
| The default value for |
| The default value for the name of the pid file in |
| If the |
| The default value for |
运行时自定义脚本
对于在写入jar 之后需要定制的脚本项目,您可以使用环境变量或 配置文件。
默认脚本支持以下环境属性:
Variable | Description |
---|---|
| The “mode” of operation. The default depends on the way the jar was built, but will usually be |
| If the |
| The root name of the pid folder ( |
| The name of the folder to put log files in ( |
| The name of the folder to read .conf files from (same folder as jar-file by default). |
| The name of the log file in the |
| The name of the app. If the jar is run from a symlink the script guesses the app name, but if it is not a symlink, or you want to explicitly set the app name this can be useful. |
| The arguments to pass to the program (the Spring Boot app). |
| The location of the |
| Options that are passed to the JVM when it is launched. |
| The explicit location of the jar file, in case the script is being used to launch a jar that it is not actually embedded in. |
| if not empty will set the |
| The time in seconds to wait when stopping the application before forcing a shutdown ( |
的 |
除了JARFILE
和APP_NAME
,上述设置可以使用.conf
文件进行配置。该文件预计在jar文件旁边,并具有相同的名称,但后缀为,.conf
而不是.jar
。例如,一个名为jar的/var/myapp/myapp.jar
将使用名为的配置文件/var/myapp/myapp.conf
。
myapp.conf。
JAVA_OPTS=-Xmx1024M LOG_FOLDER=/custom/log/folder
|
要了解如何保护这个文件,请参考 保护init.d服务的指导原则。
59.3 Microsoft Windows服务
Spring Boot应用程序可以作为Windows服务使用启动 winsw
。
独立 于Spring Boot核心的样例逐步介绍了如何为Spring Boot应用程序创建Windows服务。
60.接下来要读什么
查看Cloud Foundry, Heroku,OpenShift和 Boxfuse网站,了解有关PaaS可提供的各种功能的更多信息。这些只是四种最流行的Java PaaS提供商,因为Spring Boot非常适合基于云的部署,因此您可以自由地考虑其他提供商。
下一节继续介绍Spring Boot CLI ; 或者你可以跳转到阅读有关 构建工具插件。