部署你的应用程序

我们已经看到如何在开发模式运行一个Play应用程序, 但是run 命令不能用来在生产模式运行应用程序。当使用run, 在每个请求, Play 都用 sbt 检查,看是否有任何文件更改, 而这可能会明显影响应用程序性能。

有几种方式可以部署Play应用程序到生产模式。让我们使用推荐方式开始, 创建一个可发行的产品。

应用程序secret

在运行你的应用程序到生产模式之前, 你需要生成一个应用程序secret。要了解更多这方面的信息,参阅配置应用程序secret。 在下面的例子, 你看到的是使用-Dapplication.secret=abcdefghijk。你必须生成自己的secret来使用这个。

使用 dist 任务

dist 任务构建一个应用程序的二进制版本,你可以部署到服务器,而无须任何对sbt或activator的依赖, 服务器唯一需要的是安装好Java。

在Play控制台, 简单地键入dist:

[my-first-app] $ dist

""

这会在你的应用程序的target/universal 文件夹产生一个 ZIP 文件,包含运行应用程序需要的所有JAR文件。

要运行应用程序, 解压这个文件到目标服务器, 然后运在bin目录中的脚本。脚本的名称是你的应用程序的名称, 并且他自带二个版本, 一个 bash shell 脚本, 和一个windows .bat 脚本。

$ unzip my-first-app-1.0.zip
$ my-first-app-1.0/bin/my-first-app -Dplay.crypto.secret=abcdefghijk

你也可以从命令行,为一个生产环境指定不同的配置文件:

$ my-first-app-1.0/bin/my-first-app -Dconfig.file=/full/path/to/conf/application-prod.conf

要了解用法的说明,调用启动脚本并加上-h 选项。

对于 Unix 用户, zip 文件不持有 Unix 文件权限,所以解压后,还需要给启动脚本设置可执行权限:

$ chmod +x /path/to/bin/<project-name>

或者可以生成 tar.gz 文件。 Tar 文件持有权限。调用universal:packageZipTarball 任务而不是dist 任务即可:

activator universal:packageZipTarball

默认情况下, dist 任务在生成的包中包括 API文档。如果这是不必要的, 在build.sbt中添加这些行:

sources in (Compile, doc) := Seq.empty

publishArtifact in (Compile, packageDoc) := false

对于构建子项目, 上述的语句也应用到所有子项目的定义。

原生包

Play 使用SBT 原生包插件。原生包插件声明dist 任务以创建一个zip文件。直接调用dist 任务等同于调用下面的命令:

[my-first-app] $ universal:packageBin

可以生成许多类型的压缩包,包括:

  • tar.gz
  • OS X disk images
  • Microsoft Installer (MSI)
  • RPMs
  • Debian 包
  • 在 RPM/Debian包中的 System V / init.d 和 Upstart services

请参阅原生包插件文档 以了解更多信息。

构建服务器发布

sbt原生包插件提供了一些archetypes。Play默认使用的一个叫Java server archetype, 它启用了以下特性:

可以在这里找到完整的文档

最小化 Debian 设置

添加以下设置到你的构建:

lazy val root = (project in file("."))
  .enablePlugins(PlayScala, DebianPlugin)

maintainer in Linux := "First Lastname <[email protected]>"

packageSummary in Linux := "My custom package summary"

packageDescription := "My longer package description"

然后用这个打包:

[my-first-app] $ debian:packageBin

最小化 RPM 设置

添加以下设置到你的构建:

lazy val root = (project in file("."))
  .enablePlugins(PlayScala, RpmPlugin)

maintainer in Linux := "First Lastname <[email protected]>"

packageSummary in Linux := "My custom package summary"

packageDescription := "My longer package description"

rpmRelease := "1"

rpmVendor := "example.com"

rpmUrl := Some("http://github.com/example/server")

rpmLicense := Some("Apache v2")

然后用这个打包:

[my-first-app] $ rpm:packageBin

会出现一些错误日志。这是因为rpm 日志到 stderr 而不是 stdout。

包含额外文件到你的发布版本

任何包含在项目的dist 目录中的东西,也会通过原生包包含在发布构建中。注意在Play, dist 目录等同于src/universal 目录,在原生包自己的文档中有讲到。

Play PID 配置

Play 管理它自己的PID, 在生产配置会描述。为了告诉启动脚本将PID文件放到哪里,在dist/conf 文件夹 内的application.ini 文件中添加以下内容:

-Dpidfile.path=/var/run/${{app_name}}/play.pid
# Add all other startup settings here, too

要了解完整内容请仔细查阅 自定义 java server 文档自定义 java app 文档

发布到 Maven (或 Ivy) 仓库

你也可以发布你的应用程序到一个 Maven仓库。这个发布的JAR文件包含你的应用程序和相应的POM文件。

你必须在build.sbt 文件中配置你想要发布到的仓库:

publishTo := Some(
  "My resolver" at "https://mycompany.com/repo"
)

credentials += Credentials(
  "Repo", "https://mycompany.com/repo", "admin", "admin123"
)

然后在Play控制台, 使用publish 任务:

[my-first-app] $ publish

查阅sbt 文档 以了解更多关于解析和证书定义的信息。

在一个地方运行生产服务器

在某些情况下, 你可能不希望创建一个完整的发布版本, 事实上,你可能想要从您的项目源目录运行您的应用程序。这需要在服务上安装sbt或activator, 并且使用stage 任务来完成。

$ activator clean stage

""

这个会清理并编译你的应用程序, 检索所需的依赖项并将其复制到target/universal/stage 目录。它也创建一个bin/<start> 脚本,这里<start> 是项目的名称。脚本运行Play服务器在Unix风格系统上,同时对于Windows也有相应的bat 文件。

例如要从项目文件夹启动my-first-app 项目的应用程序,你可以:

$ target/universal/stage/bin/my-first-app -Dplay.crypto.secret=abcdefghijk

你也可以从命令行,为生产环境指定一个不同的配置文件:

$ target/universal/stage/bin/my-first-app -Dconfig.file=/full/path/to/conf/application-prod.conf

运行一个测试实例

Play 提供一个方便的实用工具,以便在prod模式运行测试应用程序。

这不是打算用于生产用途的。

要在prod模式运行一个应用程序, 运行testProd:

[my-first-app] $ testProd

使用SBT assembly插件

虽然没有正式支持, SBT assembly 插件可用于打包和运行Play应用程序。这将产生一个jar作为输出工件, 并允许你直接使用java 命令执行它。

要使用这个, 添加一个依赖插件到你的project/plugins.sbt 文件:

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")

现在添加下面的配置到你的build.sbt中:

import AssemblyKeys._

assemblySettings

mainClass in assembly := Some("play.core.server.NettyServer")

fullClasspath in assembly += Attributed.blank(PlayKeys.playPackageAssets.value)

现在你可以通过运行activator assembly构建工件了, 然后运行你的应用程序:

$ java -jar target/scala-2.XX/-assembly-.jar -Dplay.crypto.secret=abcdefghijk

当然,你需要替换为正确的项目名称, 版本和scala版本。