vlambda博客
学习文章列表

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

Project Deployment

我们已经到了旅程的终点​​。在上一章中,我们编写了一些测试来确认我们的代码工作正常。在本章中,我们会将 Spring 应用程序发布到生产环境中。我们将介绍如何逐步发布它的示例,并为您提供有关此主题的进一步阅读的指南和建议。

在本书的最后一章中,我们将介绍以下内容:

  • What will be deployed?
  • Deployment options
  • Deploying to the Cloud (AWS)

What will be deployed?

在我们部署任何东西之前,我们必须提供将要部署的所有东西。为此,我们将部署 API 模块的 JAR。 JAR 是应用程序构建的结果。我们要做的第一件事是准备发布应用程序。我们将把端口从 9000 更改为 80。打开 application.properties 文件并进行以下更改:

spring.application.name= journaler 
server.port= 80 
logging.level.root=INFO 
logging.level.com.journaler.api=DEBUG 
logging.level.org.springframework.jdbc=ERROR 
 
endpoints.health.enabled=true 
endpoints.trace.enabled=true 
endpoints.info.enabled=true 
endpoints.metrics.enabled=true 
 
spring.datasource.url=jdbc:mysql://localhost/journaler_api?useSSL=false&useUnicode=true&characterEncoding=utf-8 
spring.datasource.username=root 
spring.datasource.password=localInstance2017 
spring.datasource.tomcat.test-on-borrow=true 
spring.datasource.tomcat.validation-interval=30000 
spring.datasource.tomcat.validation-query=SELECT 1 
spring.datasource.tomcat.remove-abandoned=true 
spring.datasource.tomcat.remove-abandoned-timeout=10000 
spring.datasource.tomcat.log-abandoned=true 
spring.datasource.tomcat.max-age=1800000 
spring.datasource.tomcat.log-validation-errors=true 
spring.datasource.tomcat.max-active=50 
spring.datasource.tomcat.max-idle=10 
 
spring.jpa.hibernate.ddl-auto=update 

我们需要做的下一件事是通过执行 ./gradlew clean 命令来清理项目,如以下屏幕截图所示:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

上述命令的输出如以下屏幕截图所示:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

现在,我们将执行 ./gradlew assemble 来构建应用程序:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

上述命令的输出如下图所示:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

让我们通过执行 ls 命令列出我们项目目录的内容:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

导航到 build/libs 目录并使用 ls
命令列出该目录的内容,如以下屏幕截图所示:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

将您看到的 JAR 复制到您要保存的位置。我们将它复制到当前用户的 Desktop 中,如下图所示:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

现在,导航到您刚刚复制 JAR 文件的位置并尝试运行它,如以下屏幕截图所示:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

正如您在以下屏幕截图中看到的那样,这将失败:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

为了能够在端口 80 上运行我们的应用程序,您必须以 sudo 用户身份运行它,如以下屏幕截图所示:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

系统将要求您输入用户密码。输入并点击 Enter。应用程序将运行,如以下屏幕截图所示:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

再次确认一切正常。打开 Postman 并触发几个 API 调用,目标是端口 80 上的本地主机。

我们将在这里插入一些注释:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

我们将阅读它们:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

一旦我们确定这个构建是好的,我们就可以继续我们的部署任务的下一步。

Deployment options

在本节中,我们将解释有关 Spring 应用程序部署的选项。如您所知,我们在这个项目中使用了 Spring Boot,这意味着 Spring Boot 提供了一个公共静态 void 主入口点,可以为您启动一个嵌入式 Web 服务器。

我们最近执行的 assemble 命令为我们创建了一个胖 JAR,因此包含了所有依赖项。如果我们通过运行 $ java - jar api-0.0.1-SNAPSHOT.jar 像上一节中那样运行应用程序。

我们还将启动嵌入式服务器,我们的应用程序将开始监听 application.properties 文件中定义的端口。

Deploying the Tomcat application server

通过运行我们的 JAR,Spring Boot 将检测到您拥有 Spring MVC 控制器并将启动一个嵌入式 Apache Tomcat 实例。这是它的默认行为。

服务器运行后,您将能够访问您的应用程序,就像我们在上一节中使用 Postman 一样。

要自定义 Tomcat,我们可以使用我们的 application.properties 文件并分配其他配置,例如:

  • server.tomcat.accept-count=0: The maximum queue length for incoming connection requests when all possible request processing threads are in use.
  • server.tomcat.accesslog.buffered=true: Used when you want to buffer the output in such way that it's flushed only periodically.
  • server.tomcat.accesslog.directory=logs: The directory in which log files are created. This can be absolute or relative to the Tomcat base directory.
  • server.tomcat.accesslog.enabled=false: Enables the access log.
  • server.tomcat.accesslog.file-date-format=.yyyy-MM-dd: The date format to place in the log file name.
  • server.tomcat.accesslog.pattern=common: Format pattern for access logs
  • server.tomcat.accesslog.prefix=access_log: Log file name prefix.
  • server.tomcat.accesslog.rename-on-rotate=false: Used when you want to defer the inclusion of the date stamp in the file name until rotate time.
  • server.tomcat.accesslog.request-attributes-enabled=false: Sets request attributes for the IP address, hostname, protocol, and port used for the request.
  • server.tomcat.accesslog.rotate=true: Used when you want to enable access log rotation.
  • server.tomcat.accesslog.suffix=.log: Log file name suffix.
  • server.tomcat.additional-tld-skip-patterns=: Comma-separated list of additional patterns that match JARs which you wish to ignore for TLD scanning.
  • server.tomcat.background-processor-delay=30s: Initiates a delay between the invocation of backgroundProcess methods (if a duration suffix is not specified, seconds will be used).
  • server.tomcat.basedir=: The Tomcat base directory. If not specified, a temporary directory is used.
  • server.tomcat.internal-proxies=: A regular expression matching trusted IP addresses.
  • server.tomcat.max-connections=0: The maximum number of connections that the server accepts and processes at any given time.
  • server.tomcat.max-http-header-size=0: The maximum size, in bytes, of the HTTP message header.
  • server.tomcat.max-http-post-size=0: The maximum size, in bytes, of the HTTP post content.
  • server.tomcat.max-threads=0: The maximum number of worker threads.
  • server.tomcat.min-spare-threads=0: The minimum number of worker threads.
  • server.tomcat.port-header=X-Forwarded-Port: The name of the HTTP header used to override the original port value.
  • server.tomcat.protocol-header=: The header that holds the incoming protocol, usually named X-Forwarded-Proto.
  • server.tomcat.protocol-header-https-value=https: The value of the protocol header indicating whether the incoming request uses SSL.
  • server.tomcat.redirect-context-root=: Used to decide whether requests to the context root should be redirected by the appending path or to the path.
  • server.tomcat.remote-ip-header=: The name of the HTTP header from which the remote IP is extracted, for instance, X-FORWARDED-FOR.
  • server.tomcat.resource.cache-ttl=: The time-to-live of the static resource cache.
  • server.tomcat.uri-encoding=UTF-8: The character encoding used to decode the URI.
  • server.tomcat.use-relative-redirects=: Used to decide whether HTTP 1.1 and later location headers generated by a call to sendRedirect will use relative or absolute redirects.

以下配置特定于 Tomcat 数据源:

spring.datasource.tomcat.*= ... 

在我们的应用程序中,数据源配置如下所示:

spring.datasource.tomcat.test-on-borrow=true 
spring.datasource.tomcat.validation-interval=30000 
spring.datasource.tomcat.validation-query=SELECT 1 
spring.datasource.tomcat.remove-abandoned=true 
spring.datasource.tomcat.remove-abandoned-timeout=10000 
spring.datasource.tomcat.log-abandoned=true 
spring.datasource.tomcat.max-age=1800000 
spring.datasource.tomcat.log-validation-errors=true 
spring.datasource.tomcat.max-active=50 
spring.datasource.tomcat.max-idle=10 

Deploying to the Java EE application server

要将 Spring 应用程序部署到主流 Java EE 应用程序服务器之一,您需要对代码进行一些更改,然后您的项目就准备就绪了。为此,我们需要一个 WAR 版本而不是 JAR。

打开 build.gradle 并更新它,以便应用 Gradle WAR 插件:

buildscript { 
    ext { 
        kotlinVersion = '1.2.21' 
        springBootVersion = '2.0.0.M4' 
    } 
    repositories { 
        mavenCentral() 
        maven { url "https://repo.spring.io/snapshot" } 
        maven { url "https://repo.spring.io/milestone" } 
    } 
    dependencies { 
        classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}") 
        classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${kotlinVersion}") 
        classpath("org.jetbrains.kotlin:kotlin-allopen:${kotlinVersion}") 
    } 
} 
 
apply plugin: 'kotlin' 
apply plugin: 'kotlin-spring' 
apply plugin: 'eclipse' 
apply plugin: 'org.springframework.boot' 
apply plugin: 'io.spring.dependency-management' 
apply plugin: 'war' 
 
group = 'com.journaler' 
version = '0.0.1-SNAPSHOT' 
sourceCompatibility = 1.8 
 
compileKotlin { 
    kotlinOptions.jvmTarget = "1.8" 
} 
compileTestKotlin { 
    kotlinOptions.jvmTarget = "1.8" 
} 
 
repositories { 
    mavenCentral() 
    maven { url "https://repo.spring.io/snapshot" } 
    maven { url "https://repo.spring.io/milestone" } 
} 
 
dependencies { 
    compile 'org.springframework.boot:spring-boot-starter-security' 
    compile 'org.springframework:spring-context' 
    compile 'org.springframework:spring-aop' 
    compile 'org.springframework.boot:spring-boot-starter' 
    compile 'org.springframework.boot:spring-boot-starter-web' 
    compile 'org.springframework.boot:spring-boot-starter-actuator' 
    compile 'org.springframework:spring-web'
    compile 'org.springframework:spring-webmvc' 
    runtime 'mysql:mysql-connector-java' 
    compile 'org.springframework.boot:spring-boot-starter-data-jpa' 
    compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${kotlinVersion}" 
    compile "org.jetbrains.kotlin:kotlin-reflect:${kotlinVersion}" 
    testCompile 'org.springframework.boot:spring-boot-starter-test' 
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' 
} 

由于我们使用 Gradle,以下代码将我们的 servlet 容器标记为已提供:

providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat' 

需要进行另一次修改。我们必须改变我们的 ApiApplication 类:

package com.journaler.api 
 
import org.springframework.boot.SpringApplication 
import org.springframework.boot.autoconfigure.SpringBootApplication 
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer 
import org.springframework.boot.builder.SpringApplicationBuilder  
 
@SpringBootApplication 
class ApiApplication : SpringBootServletInitializer() { 
    override fun configure(application: SpringApplicationBuilder): SpringApplicationBuilder { 
        return application.sources(ApiApplication::class.java) 
    } 
} 
 
fun main(args: Array<String>) { 
    SpringApplication.run(ApiApplication::class.java, *args) 
} 

现在,我们准备好生成 WAR。打开终端并使用 Gradle 的 ./gradlew clean 命令,如以下屏幕截图所示:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

上述命令完成后,运行 Gradle 的 .gradlew assemble 命令,如下图所示:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

在前面的命令完成它的过程之后,我们应该准备好我们的 WAR。导航到 libs 目录,如以下屏幕截图所示:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

现在,使用 ls 命令列出目录中的文件,如以下屏幕截图所示:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

如您所见,api-0.0.1-SNAPSHOT.war 构建可用。

Deploying to the Cloud (AWS)

今天,Amazon Web Services (AWS) 是最流行的托管应用程序平台。 AWS 是 Amazon.com 的子公司,以付费订阅的方式为个人、公司和政府提供按需云计算平台。它受欢迎的原因是它提供了可靠、可扩展和廉价的云计算服务。

由于这是本章的最后一部分,我们将逐步指导您完成部署到 AWS 的过程。我们将向您展示如何使用 AWS Elastic Beanstalk 部署我们的 API Spring Boot 应用程序。我们还将向您展示如何通过使用环境变量来自定义 Spring Boot 配置。

AWS Elastic Beanstalk 提供约定优于配置,但它仍然使我们能够在需要时进行调整。 Elastic Beanstalk 是一种托管服务,旨在部署和扩展 Web 应用程序和服务。它支持各种编程语言,以及各种 Web 和应用程序服务器,例如 Apache、Nginx、Passenger、Tomcat 和 IIS。

为了能够部署我们的应用程序,我们需要设置一个 AWS 账户。您可以在此处注册免费帐户以试用 AWS Elastic Beanstalk:https://aws.amazon.com/免费/

打开链接。您应该会看到以下 AWS 免费套餐页面:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

点击 创建免费帐户 按钮。将出现注册表:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

填充您的数据并点击继续。然后,联系信息表格会出现:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

插入您的个人数据并点击创建帐户并继续按钮。然后,会出现下面的支付信息表单:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署
As it says on the AWS website: Please type in your payment information so that we can verify your identity. We will not charge you unless your usage exceeds the AWS Free Tier limits.

填充您的数据并单击 安全提交 按钮继续。然后,会出现下面的Phone Verification页面:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

按照电话验证说明操作,直到验证过程完成:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

点击 Continue 并通过点击 Free 按钮选择 基本计划

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

恭喜!您已成功注册 AWS 账户:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

现在,单击右上角的 登录控制台 按钮。 登录 表单将出现:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

填写您的信息,然后单击 下一步 按钮继续。填写密码并继续前进。几秒钟后,您将被重定向到 AWS 管理控制台:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

现在,我们准备好部署我们的应用程序了!

By the time you read this book, the Amazon AWS registration procedure and registration flow may have changed. In that case, we encourage you to simply follow the registration steps since it's easy to register and understand each step.

通过单击 构建 Web 应用程序 链接打开 Elastic Beanstalk 控制台。 Elastic Beanstalk 控制台 将打开:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

对于 Application name,输入 Journaler API,对于 Description,输入 Example application。单击 下一步 按钮。将出现一个名为 New Environment 的页面:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

单击 创建 Web 服务器 按钮。将出现一个名为 Environment Type 的页面:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

对于 预定义配置,选择 Java。对于 环境类型,选择 单实例。单击 下一步 按钮继续。将出现一个名为 Application Version 的页面:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

选择上传你自己的,然后点击选择文件按钮。导航到您保存 JAR 的位置并选择它:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

点击 Next 按钮上传 JAR:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

上传这个版本的应用程序需要一些时间。将出现以下环境信息页面:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

在继续之前单击 检查可用性 按钮。检查完成后,我们的 API URL 会变成绿色:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

写下您的应用程序的完整 URL。在我们的例子中,这将是以下内容:

journalerapi-env.us-east-2.elasticbeanstalk.com

现在,单击 下一步 按钮。将出现以下 Additional Resources 页面:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

选中这两个复选框并单击 Next 按钮。填充以下 配置详细信息 页面:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

单击 下一步 按钮继续。将出现以下 Environment Tags 页面:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

单击 下一步 按钮继续。将出现以下 RDS 配置 页面:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

对于用户名和密码,输入我们在 application.properties 文件中使用的值。用这些数据填写表格,然后单击 下一步 按钮继续。将出现以下 VPC 配置 页面:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

选择 关联公共 IP 地址

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

完成后,单击 下一步 按钮继续。将出现以下 Permissions 页面:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

单击 下一步 按钮。将出现以下 Review 页面:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

查看配置并单击 Launch 以完成向导。部署将开始:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

完成部署需要一些时间。等到部署完成:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

恭喜!您已成功部署应用程序!在我们尝试之前,还有一些事情要做。

默认情况下,我们的 Spring Boot 应用程序将侦听端口 80。 Elastic Beanstalk 假定应用程序将侦听端口 5000。我们必须解决这个问题。

在您环境中的 配置 页面上,找到 软件配置

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署
Observe the Software Configuration option in the Configuration page

单击设置图标并滚动到页面底部:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

添加 5000SERVER_PORT 值:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

点击 Apply 按钮保存更改。除了配置应用程序侦听的端口外,我们还必须指定环境变量来配置应用程序将使用的数据库。

让我们获取数据库的端点 URL。在 Environment Configuration 页面的 Data Tier 部分下,您会在 RDS

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

写下来。在我们的例子中,如下所示:

aa5d0lzzf02dnm.cbpdar2dvspv.us-east-2.rds.amazonaws.com:3306

返回 Environment Properties 部分并使用以下内容对其进行扩展:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

总而言之,我们添加了以下环境属性:

  • SERVER_PORT: 5000
  • SPRING_DATASOURCE_PASSWORD: localInstance2017
  • SPRING_DATASOURCE_URL: jdbc:mysql://aa5d0lzzf02dnm.cbpdar2dvspv.us-east-2.rds.amazonaws.com:3306/ebdb (you will use your DB URL)
注意! URL 以以下结尾: /ebdb
  • SPRING_DATASOURCE_USERNAME: root
  • SPRING_JPA_DATABASE_PLATFORM: org.hibernate.dialect.MySQL5Dialect
  • SPRING_JPA_HIBERNATE_DDL_AUTO: update

单击 Apply 以保存更改并等待更改应用。现在,您已准备好试用 API。打开 Postman 并针对我们 API 的生产 URL 执行几个 API 调用。

准备好应用程序可能需要一些时间!刷新应用程序的 URL,直到错误 502 停止出现。当您看到 Spring 的 Whitelabel Error Page 时,您将知道应用程序已准备就绪:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

让我们插入一些注释。我们将用我们的生产 URL 替换我们的 localhost URL(输入您在部署期间记下的 URL):

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

插入注释后,验证它们是否确实存在:

读书笔记《building-applications-with-spring-5-and-kotlin》项目部署

最后,我们可以确认我们的 Rest API 已启动并运行!现在,您可以将其公开给客户端应用程序。您可以将它与 Angular 客户端、Android、iOS 应用程序或您选择的任何其他应用程序一起使用。

一旦发布了应用程序的新版本(当新 JAR 准备就绪时),部署它就非常简单了。您所要做的就是使用 AWS Elastic Beanstalk 控制台的登录页面并上传新构建。我们设置的所有环境属性都将被使用,应用程序将立即准备就绪。

由您决定使用哪种部署方法。调查和比较其他选项。写下所有的优点和缺点。尝试每一个。我们推荐 AWS 作为我们首选的应用程序部署方法,因为它易于配置和部署,并且稳定且灵活。

Summary

在本章中,我们将应用程序发布到生产环境中。这是完成本书旅程的完美方式。在本书的章节中,我们对应用程序进行了雕刻,并在最后阶段将其部署到 AWS。 Spring 是一个很大的框架,它可能需要一些时间来学习它所提供的一切。我们鼓励您继续学习和提高您的 Spring 知识。尽可能多地编写代码并研究 Spring 为您提供的所有选项。正如我们在上一节末尾已经提到的,尝试所有可以使用的部署选项。了解它们中的每一个都可能是一个巨大的优势!

如需进一步阅读,我们建议您查看针对特定 Spring 相关领域的官方 Spring 文档或书籍。不要犹豫,开始行动。创建一个新的存储库并开始编写新的 Spring 应用程序!