如何在谷歌云中部署 Spring Boot 应用程序?

Posted

技术标签:

【中文标题】如何在谷歌云中部署 Spring Boot 应用程序?【英文标题】:How to deploy a spring boot app in google cloud? 【发布时间】:2020-11-22 01:07:56 【问题描述】:

我正在尝试将 Java Spring Boot 应用部署到 Google Cloud,但遇到了一些问题。 我尝试了两种方法:

    https://cloud.google.com/appengine/docs/flexible/java/quickstart https://www.baeldung.com/spring-boot-google-app-engine

这是我使用第一种部署方法(gcloud app deploy)时遇到的错误:

ERROR: gcloud crashed (KeyError): None

这是我使用第二种部署方法(maven deploy)时遇到的错误:

Failed to execute goal com.google.cloud.tools:appengine-maven-plugin:1.3.2:deploy (default-cli) on project server: Execution default-cli of goal com.google.cloud.tools:appengine-maven-plugin:1.3.2:deploy failed: Non zero exit: 1

我觉得我错过了一些部署步骤 - 但我不知道是哪个。 我正在做的是:

    从 console.cloud.google.com 创建项目。 打开 Google SDK Shell。 转到文件夹。 “google init”选择项目和用户。 '谷歌应用创建'。 “google app deploy”/使用“mvn clean package appengine:deploy -P cloud-gcp”或“mvn clean -DskipTests appengine:deploy”从 maven 部署。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.5.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>server</groupId>
    <artifactId>server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>server</name>
    <description>Description</description>
    <packaging>war</packaging>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>11</java.version>
        <servlet.version>4.0.0</servlet.version>

    </properties>

    <dependencies>
        <dependency>
            <groupId>com.google.appengine</groupId>
            <artifactId>appengine-api-1.0-sdk</artifactId>
            <version>1.9.60</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-rest</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-text</artifactId>
            <version>1.8</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>org.flywaydb</groupId>
            <artifactId>flyway-core</artifactId>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.10.5</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.10.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.10.5</version>
            <scope>runtime</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.humble/humble-video-all -->
        <dependency>
            <groupId>io.humble</groupId>
            <artifactId>humble-video-all</artifactId>
            <version>0.1.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
        <dependency>
            <groupId>commons-cli</groupId>
            <artifactId>commons-cli</artifactId>
            <version>1.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-starter</artifactId>
            <version>1.0.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-gcp-starter-sql-mysql</artifactId>
            <version>1.0.0.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>com.google.cloud.tools</groupId>
                <artifactId>appengine-maven-plugin</artifactId>
                <version>1.3.2</version>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.properties

*db config*

spring.cloud.appId=*id*

spring.cloud.gcp.sql.instance-connection-name=*copied name from cloud*
spring.cloud.gcp.sql.database-name=*db name*

appengine/app.yaml

runtime: java11
env: flex
env_variables:
  SPRING_PROFILES_ACTIVE: "gcp,mysql"
health_check:
  enable_health_check: False
handlers:
  - url: /.*
    script: this field is required, but ignored
manual_scaling:
  instances: 1

^ 也只尝试过:

runtime: java11

webapp/WEB-INF/appengine-web.xml

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
    <version>1</version>
    <threadsafe>true</threadsafe>
    <runtime>java11</runtime>
</appengine-web-app>

编辑: 使用标志“-e”运行 maven 部署会得到以下跟踪:

org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal com.google.cloud.tools:appengine-maven-plugin:1.3.2:deploy (default-cli) on project server: Execution default-cli of goal com.g
oogle.cloud.tools:appengine-maven-plugin:1.3.2:deploy failed: Non zero exit: 1
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:215)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: org.apache.maven.plugin.PluginExecutionException: Execution default-cli of goal com.google.cloud.tools:appengine-maven-plugin:1.3.2:deploy failed: Non zero exit: 1
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:148)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)
Caused by: com.google.cloud.tools.appengine.api.AppEngineException: Non zero exit: 1
    at com.google.cloud.tools.appengine.cloudsdk.process.NonZeroExceptionExitListener.onExit (NonZeroExceptionExitListener.java:28)
    at com.google.cloud.tools.appengine.cloudsdk.internal.process.DefaultProcessRunner.syncRun (DefaultProcessRunner.java:209)
    at com.google.cloud.tools.appengine.cloudsdk.internal.process.DefaultProcessRunner.run (DefaultProcessRunner.java:137)
    at com.google.cloud.tools.appengine.cloudsdk.CloudSdk.runGcloudCommand (CloudSdk.java:179)
    at com.google.cloud.tools.appengine.cloudsdk.CloudSdk.runAppCommandInWorkingDirectory (CloudSdk.java:138)
    at com.google.cloud.tools.appengine.cloudsdk.CloudSdkAppEngineDeployment.deploy (CloudSdkAppEngineDeployment.java:87)
    at com.google.cloud.tools.maven.DeployMojo.execute (DeployMojo.java:107)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo (DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject (LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build (SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute (LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute (DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute (DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute (MavenCli.java:957)
    at org.apache.maven.cli.MavenCli.doMain (MavenCli.java:289)
    at org.apache.maven.cli.MavenCli.main (MavenCli.java:193)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:566)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced (Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch (Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode (Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main (Launcher.java:347)

有人知道出了什么问题吗? 谢谢!

【问题讨论】:

为什么会有一个xml和一个yaml?我们将 standard 环境与 java11 和 app.yaml 一起使用。请注意,您也可以使用 Google Cloud Run。还要检查你是否有最新的 clouddk 版本并尝试gcloud feedback 删除了 xml 文件并添加了 'env:standard' 属性。我仍然遇到同样的错误。 【参考方案1】:

有几个挑战:

    GCP 标准环境提供的是 Jetty,而不是 Tomcat

    Google 已修复更高版本插件中的 app.yaml / appengine-web.xml 问题

        <plugin>
          <groupId>com.google.cloud.tools</groupId>
          <artifactId>appengine-maven-plugin</artifactId>
          <version>2.3.0</version>
        </plugin>

在您的 &lt;dependencyManagement/&gt; 导入结束时:

      <!-- org.springframework.cloud:spring-cloud-gcp-dependencies -->
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-gcp-dependencies</artifactId>
        <version>1.2.4.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

并相应地利用 &lt;dependencies/&gt; 中的更新版本。

我建议您将应用程序打包在一个单独的 JAR 中,并将依赖项包含在您的 pom.xml 中,例如:

    <dependency>
      <groupId>GROUP</groupId>
      <artifactId>ARTIFACT</artifactId>
      <version>VERSION</version>
      <exclusions>
        <exclusion>
          <artifactId>commons-logging</artifactId>
          <groupId>commons-logging</groupId>
        </exclusion>
        <exclusion>
          <groupId>javax.transaction</groupId>
          <artifactId>javax.transaction-api</artifactId>
        </exclusion>
        <exclusion>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
      </exclusions>
    </dependency>

其中 GROUP:ARTIFACT:VERSION 是您的应用程序 JAR 的实际 Maven 坐标。

WEB-INF 文件夹中,添加您的appengine-web.xml(类似):

<?xml version="1.0" encoding="utf-8"?>
<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
  <application>GROUP</application>
  <service>ARTIFACT</service>
  <version>VERSION</version>
  <runtime>java8</runtime>
  <basic-scaling>
    <max-instances>1</max-instances>
    <idle-timeout>5m</idle-timeout>
  </basic-scaling>
  <instance-class>B1</instance-class>
  <threadsafe>true</threadsafe>
  <sessions-enabled>true</sessions-enabled>
  <env-variables>
    <env-var name="SPRING_PROFILES_ACTIVE" value="gcp,mysql"/>
  </env-variables>
  <system-properties>
    <property name="java.util.logging.config.file" value="WEB-INF/logging.properties"/>
  </system-properties>
</appengine-web-app>

其中 GROUP、ARTIFACT 和 VERSION 分别对应于您的 JAR 的 Maven 工件 groupId、artifactId 和 version。

更新插件后,我发现我不再需要app.yaml 文件。您需要包含logging.properties

# Set the default logging level for all loggers to WARNING
.level = WARNING

最后,将您的 GROUP:ARTIFACT:VERSION jar 重新打包到您的 POM 中(注意必须为您的应用程序定义 $start-class):

  <build>
    <pluginManagement>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-war-plugin</artifactId>
        </plugin>
        <plugin>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-maven-plugin</artifactId>
          <executions>
            <execution>
              <goals>
                <goal>build-info</goal>
                <goal>repackage</goal>
              </goals>
            </execution>
          </executions>
          <configuration>
            <mainClass>$start-class</mainClass>
          </configuration>
        </plugin>
      </plugins>
    </pluginManagement>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <profiles>
            <profile>gcp</profile>
            <profile>mysql</profile>
          </profiles>
        </configuration>
      </plugin>
    </plugins>
  </build>

使用mvn clean package appengine:deploy 进行部署。这个article有更多细节。

【讨论】:

以上是关于如何在谷歌云中部署 Spring Boot 应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

如果我将 Spring Boot 应用程序部署到谷歌云,我应该使用应用引擎还是计算引擎 [重复]

在谷歌云中部署后,Angular 应用程序无法调用 Flask 服务器 API

在谷歌云平台部署python脚本

如何使用谷歌应用引擎将 php 项目部署到谷歌云中?

试图在谷歌云中查找已部署 python 函数的当前项目 ID 会出错

如何在谷歌云上正确托管 node.js 应用程序?