在 Compute Engine 上运行 Java Bookshelf 应用

本教程介绍如何在 Compute Engine 上运行 Java Bookshelf 应用。请按照本教程将现有 Java 网页应用部署到 Compute Engine。您应该完整阅读 App Engine 标准环境教程中的 Bookshelf 应用文档。

目标

  • 将 Bookshelf 示例应用部署到单个 Compute Engine 实例。
  • 通过使用托管实例组横向扩缩该应用。
  • 通过 HTTP 负载平衡来处理流量。
  • 通过自动扩缩来应对流量变化。

费用

本教程使用 Google Cloud Platform (GCP) 的以下收费组件:

  • Compute Engine
  • Cloud Storage
  • Cloud Datastore
  • Stackdriver Logging
  • Cloud Pub/Sub

请使用价格计算器根据您的预计使用情况来估算费用。 GCP 新用户可能有资格免费试用

准备工作

  1. 登录您的 Google 帐号。

    如果您还没有 Google 帐号,请注册新帐号

  2. 选择或创建 Google Cloud Platform 项目。

    转到“管理资源”页面

  3. 确保您的 Google Cloud Platform 项目已启用结算功能。

    了解如何启用结算功能

  4. 启用Cloud Datastore、Cloud Storage 和 Cloud Pub/Sub API。

    启用 API

  5. 安装并初始化 Cloud SDK
  6. 安装 Java 8Maven

初始化 Cloud Datastore

Bookshelf 应用使用 Cloud Datastore 存储图书。要在您的项目中首次初始化 Cloud Datastore,请执行以下操作:

  1. 在 GCP Console 上打开 Cloud Datastore

  2. 为您的数据存储区选择一个区域,然后点击继续。当您看到创建实体页面后,请关闭相应窗口。Bookshelf 应用已准备好在 Cloud Datastore 上创建实体。

创建 Cloud Storage 存储分区

以下说明介绍如何创建 Cloud Storage 存储分区。存储分区是 Cloud Storage 中用于存放数据的基本容器。

  1. 在一个终端窗口中,输入以下命令:

    gsutil mb gs://[YOUR-BUCKET-NAME]

    [YOUR-BUCKET-NAME] 表示您的 Cloud Storage 存储分区的名称。

  2. 要在 Bookshelf 应用中查看上传的图片,请将存储分区的默认访问控制列表 (ACL) 设置为 public-read

    gsutil defacl set public-read gs://[YOUR-BUCKET-NAME]

克隆示例应用

示例应用可在 GitHub 上的 GoogleCloudPlatform/getting-started-java 下找到。

  1. 克隆代码库。

    git clone https://github.com/GoogleCloudPlatform/getting-started-java.git
    
  2. 转到示例目录。

    cd getting-started-java/bookshelf/6-gce
    

配置应用

  1. 打开 makeBookshelf 文件进行修改。
  2. BUCKET 变量设置为您之前创建的存储分区的名称。
  3. 您可以选择将 ZONE=us-central1-f 更改为其他地区。
  4. 让该脚本可执行:

    chmod +x makeBookshelf
    
  5. 打开 pom.xml 进行修改。

  6. 使用存储分区的名称设置 bookshelf.bucket 属性。

  7. 保存并关闭这两个文件。

    在本地计算机上运行应用

    1. 启动本地网络服务器:

      mvn -Plocal clean jetty:run-exploded -DprojectID=[YOUR-PROJECT-ID]
      

      其中 [YOUR-PROJECT-ID] 是您的项目 ID。

    2. 在网络浏览器中输入此地址:

      http://localhost:8080

    要停止本地网络服务器,请按 Control+C

    部署到单个实例

    单实例部署

    此部分逐步介绍了如何在 Compute Engine 上运行应用的单个实例。

    将代码推送到代码库

    您可以使用 Cloud Source Repositories 在项目中创建一个 Git 代码库,并将您的应用代码上传到其中。然后,您的实例可以在启动过程中从该代码库中拉取应用代码的最新版本。这样,更新您的应用就不需要配置新映像或实例;您只需重新启动现有实例或创建一个新实例,非常方便。

    要创建 Compute Engine 实例并将应用推送到该实例,请输入以下命令:

    ./makeBookshelf gce
    

    该命令将执行以下操作:

    • 构建项目并创建 Java WAR 文件。
    • 将 WAR 文件和一些脚本上传到您之前为存储映像而创建的 Cloud Storage 存储分区。
    • 创建 Compute Engine 实例并允许其访问 Stackdriver Logging、Cloud Storage 和 Cloud Datastore。
    • 传递有关 Cloud Storage 存储分区的元数据。
    • 指定启动脚本。
    mvn clean package
    
    gsutil cp -r target/${WAR} gce/base gs://${BUCKET}/gce/
    
    gcloud compute firewall-rules create allow-http-bookshelf \
      --allow tcp:80 \
      --source-ranges 0.0.0.0/0 \
      --target-tags ${TAGS} \
      --description "Allow port 80 access to instances tagged with ${TAGS}"
    
    gcloud compute instances create my-app-instance \
      --machine-type=${MACHINE_TYPE} \
      --scopes=${SCOPES} \
      --metadata-from-file startup-script=${STARTUP_SCRIPT} \
      --zone=${ZONE} \
      --tags=${TAGS} \
      --image-family=${IMAGE_FAMILY} \
      --image-project=${IMAGE_PROJECT} \
      --metadata BUCKET=${BUCKET}

    makeBookshelf 脚本定义多个变量:

    ZONE=us-central1-f
    
    GROUP=frontend-group
    TEMPLATE=$GROUP-tmpl
    MACHINE_TYPE=g1-small
    IMAGE_FAMILY=debian-8
    IMAGE_PROJECT=debian-cloud
    STARTUP_SCRIPT=gce/startup-script.sh
    SCOPES="datastore,userinfo-email,logging-write,storage-full,cloud-platform"
    TAGS=http-server
    
    MIN_INSTANCES=1
    MAX_INSTANCES=10
    TARGET_UTILIZATION=0.6
    
    SERVICE=frontend-web-service
    WAR=bookshelf-1.0-SNAPSHOT.war

    该实例需要大约五分钟时间来运行启动脚本。您可以输入以下命令检查实例的进度:

    gcloud compute instances get-serial-port-output my-app-instance --zone us-central1-f
    

    启动脚本完成后,您可以在此位置检查新实例上的启动日志:/var/logs/daemon.log

    实例名称是 my-app-instance。您可以输入以下命令来获取实例的外部 IP 地址:

    gcloud compute instances list
    

    要查看应用的运行情况,请在浏览器中输入以下网址:

    http://[YOUR_INSTANCE_IP]
    

    要删除实例,请输入以下命令:

    ./makeBookshelf down
    

    使用启动脚本初始化实例

    现在,您可以通过 Compute Engine 实例访问您的代码,您需要一种方法来指示实例下载并运行这些代码。实例可以有一个每当其启动或重新启动时都会执行的启动脚本。

    该启动脚本执行以下任务:

    • 安装 Java 8 并将其设为默认版本。

    • 安装并配置 Jetty。

    • 将 Cloud Storage 存储分区中的 Java WAR 文件复制到 Jetty 的 webapps,并将其重命名为 root.war。这将使其成为根 servlet,因此不需要在网址中命名。

    • 安装 Stackdriver Logging 代理,并将其配置为监控应用日志。这表示,您在本教程前面步骤中配置的日志记录将上传,就像是您在使用 App Engine 柔性环境一样。

    set -e
    set -v
    
    # Talk to the metadata server to get the project id
    PROJECTID=$(curl -s "http://metadata.google.internal/computeMetadata/v1/project/project-id" -H "Metadata-Flavor: Google")
    BUCKET=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/attributes/BUCKET" -H "Metadata-Flavor: Google")
    
    echo "Project ID: ${PROJECTID}  Bucket: ${BUCKET}"
    
    # get our file(s)
    gsutil cp "gs://${BUCKET}/gce/"** .
    
    # Install dependencies from apt
    apt-get update
    apt-get install -t jessie-backports -yq openjdk-8-jdk
    
    # Make Java8 the default
    update-alternatives --set java /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java
    
    # Jetty Setup
    mkdir -p /opt/jetty/temp
    mkdir -p /var/log/jetty
    
    # Get Jetty
    curl -L https://repo1.maven.org/maven2/org/eclipse/jetty/jetty-distribution/9.3.8.v20160314/jetty-distribution-9.3.8.v20160314.tar.gz -o jetty9.tgz
    tar xf jetty9.tgz  --strip-components=1 -C /opt/jetty
    
    # Add a Jetty User
    useradd --user-group --shell /bin/false --home-dir /opt/jetty/temp jetty
    
    cd /opt/jetty
    # Add running as "jetty"
    java -jar /opt/jetty/start.jar --add-to-startd=setuid
    cd /
    
    # very important - by renaming the war to root.war, it will run as the root servlet.
    mv bookshelf-1.0-SNAPSHOT.war /opt/jetty/webapps/root.war
    
    # Make sure "jetty" owns everything.
    chown --recursive jetty /opt/jetty
    
    # Configure the default paths for the Jetty service
    cp /opt/jetty/bin/jetty.sh /etc/init.d/jetty
    echo "JETTY_HOME=/opt/jetty" > /etc/default/jetty
    {
      echo "JETTY_BASE=/opt/jetty"
      echo "TMPDIR=/opt/jetty/temp"
      echo "JAVA_OPTIONS=-Djetty.http.port=80"
      echo "JETTY_LOGS=/var/log/jetty"
    } >> /etc/default/jetty
    
    # -Dorg.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.JavaUtilLog
    
    # Reload daemon to pick up new service
    systemctl daemon-reload
    
    # Install logging monitor. The monitor will automatically pickup logs sent to syslog.
    curl -s "https://storage.googleapis.com/signals-agents/logging/google-fluentd-install.sh" | bash
    service google-fluentd restart &
    
    service jetty start
    service jetty check
    
    echo "Startup Complete"

    创建和配置 Compute Engine 实例

    1. 创建 Compute Engine 实例。以下命令可创建新实例,允许其访问 GCP 服务,并运行启动脚本。实例名称是 my-app-instance

      Linux/macOS

      gcloud compute instances create my-app-instance \
          --image-family=debian-9 \
          --image-project=debian-cloud \
          --machine-type=g1-small \
          --scopes userinfo-email,cloud-platform \
          --metadata app-location=$BOOKSHELF_DEPLOY_LOCATION \
          --metadata-from-file startup-script=gce/startup-script.sh \
          --zone us-central1-f \
          --tags http-server
      

      Windows

      gcloud compute instances create my-app-instance ^
          --image-family=debian-9 ^
          --image-project=debian-cloud ^
          --machine-type=g1-small ^
          --scopes userinfo-email,cloud-platform ^
          --metadata-from-file startup-script=gce/startup-script.sh ^
          --zone us-central1-f ^
          --tags http-server
      

    2. 检查实例创建的进度。

      gcloud compute instances get-serial-port-output my-app-instance --zone us-central1-f
      

      如果启动脚本已完成,您会在命令输出末尾附近看到 Finished running startup script

    3. 创建一条防火墙规则以允许流量进入您的实例。

      Linux/macOS

      gcloud compute firewall-rules create default-allow-http-8080 \
          --allow tcp:8080 \
          --source-ranges 0.0.0.0/0 \
          --target-tags http-server \
          --description "Allow port 8080 access to http-server"
      

      Windows

      gcloud compute firewall-rules create default-allow-http-8080 ^
          --allow tcp:8080 ^
          --source-ranges 0.0.0.0/0 ^
          --target-tags http-server ^
          --description "Allow port 8080 access to http-server"
      

    4. 获取您的实例的外部 IP 地址。

      gcloud compute instances list
      
    5. 要查看应用是否正在运行,请转到 http://[YOUR_INSTANCE_IP]:8080

      其中 [YOUR_INSTANCE_IP] 是您的实例的外部 IP 地址。

    管理和监控实例

    您可以使用 Google Cloud Platform Console 来监控和管理您的实例。

    要查看正在运行的实例并使用 ssh 连接到该实例,请转到计算 > Compute Engine

    要查看 Compute Engine 资源生成的所有日志,请转到监控 > 日志Stackdriver Logging 会自动配置为从各种常用服务(包括 syslog)收集日志。

    使用多个实例进行横向扩缩

    使用托管实例的多实例部署

    Compute Engine 可轻松进行横向扩缩。通过使用托管实例组和 Compute Engine 自动调节程序,Compute Engine 可以在需要时自动创建应用的新实例,并在需求较低时关闭实例。您可以设置 HTTP 负载平衡器将流量分配给托管实例组中的实例。

    部署脚本

    示例应用包含一个自动执行以下部署步骤的脚本。该脚本名为 deploy.sh,旨在为能够自动扩缩和执行负载平衡的完整应用部署资源(请参阅使用多个实例进行横向扩缩)。

    您可以自行完成以下各个步骤,或者从 gce 目录运行 gce/deploy.sh

    创建托管实例组

    托管实例组是基于同一实例模板的一组同构实例。实例模板定义实例的配置,包括源映像、磁盘大小、范围和元数据(包括启动脚本)。

    1. 首先,创建一个模板。

      ./makeBookshelf gce-many
      
    2. 创建实例组。

      gcloud compute instance-groups managed \
        create ${GROUP} \
        --base-instance-name ${GROUP} \
        --size ${MIN_INSTANCES} \
        --template ${TEMPLATE} \
        --zone ${ZONE}

      --size 参数指定组中实例的数量。在所有实例都已运行完启动脚本后,您可以使用其外部 IP 地址和端口 8080 分别访问这些实例。要查找这些实例的外部 IP 地址,请输入 gcloud compute instances list。托管实例的名称以您在 --base-instance-name 参数中指定的同一前缀 my-app 开头。

    创建负载平衡器

    单个实例可用于测试或调试,但要处理网络流量,最好使用负载平衡器将流量自动引导至可用实例。要创建负载平衡器,请按照以下步骤操作。

    1. 创建运行状况检查。负载平衡器会使用运行状况检查来确定哪些实例能够处理流量。

      gcloud compute http-health-checks create ah-health-check \
        --request-path /_ah/health \
        --port 80
    2. 创建一个指定端口。HTTP 负载平衡器会查找 http 服务以了解将流量引导至哪个端口。在您现有的实例组中,为端口 8080 指定名称 http

    3. 创建后端服务。后端服务是经过负载平衡后的流量的目标。它确定了应将流量引导至哪个实例组,以及要使用哪种运行状况检查。

      gcloud compute backend-services create $SERVICE \
        --http-health-checks ah-health-check
    4. 添加后端服务。

      gcloud compute backend-services add-backend $SERVICE \
        --instance-group $GROUP \
        --zone $ZONE
    5. 创建一个网址映射和代理。网址映射定义哪些网址应该引导至哪些后端服务。在此示例中,所有流量都由一个后端服务处理。如果您想对多个区域或组之间的请求做负载平衡,则可以创建多个后端服务。代理会接收流量并使用网址映射将其转发到后端服务。

      1. 创建网址映射。

        gcloud compute url-maps create $SERVICE-map \
          --default-service $SERVICE
      2. 创建代理。

        gcloud compute target-http-proxies create $SERVICE-proxy \
          --url-map $SERVICE-map
    6. 创建全局转发规则。全局转发规则会将公共 IP 地址和端口绑定到代理。

      gcloud compute forwarding-rules create $SERVICE-http-rule \
        --global \
        --target-http-proxy $SERVICE-proxy \
        --port-range 80

    配置自动调节程序

    负载平衡器可确保流量分配给所有正常运行的实例。但如果您的实例需要处理的流量过多,该怎么办?您可以手动添加更多实例,但更好的解决方案是配置 Compute Engine 自动扩缩程序,以根据流量需求自动创建和删除实例。

    1. 创建自动调节程序。

      gcloud compute instance-groups managed set-autoscaling \
        $GROUP \
        --max-num-replicas $MAX_INSTANCES \
        --target-load-balancing-utilization $TARGET_UTILIZATION \
        --zone $ZONE

      以上命令会在托管实例组(可自动扩大至最多 10 个实例)上创建一个自动扩缩程序。系统会在负载平衡器的利用率高于 50% 时添加新实例,并在利用率低于 50% 时移除新实例。

    2. 创建防火墙规则。

      Linux/macOS

      gcloud compute firewall-rules create default-allow-http-8080 \
          --allow tcp:8080 \
          --source-ranges 0.0.0.0/0 \
          --target-tags http-server \
          --description "Allow port 8080 access to http-server"
      

      Windows

      gcloud compute firewall-rules create default-allow-http-8080 ^
          --allow tcp:8080 ^
          --source-ranges 0.0.0.0/0 ^
          --target-tags http-server ^
          --description "Allow port 8080 access to http-server"
      

    3. 检查进度,直到至少有一个实例显示 HEALTHY 为止。

      gcloud compute backend-services get-health frontend-web-service --global
      

    查看您的应用

    1. 获取负载平衡器的转发 IP 地址。

      gcloud compute forwarding-rules list --global
      

      您的转发规则 IP 地址位于 IP_ADDRESS 列中。

    2. 在浏览器中,输入列表中的 IP 地址。现在,您的应用已经过了负载平衡和自动调节,正在 Google Compute Engine 上运行。

    管理和监控您的部署

    管理多个实例就像管理单个实例一样简单。您可以使用 GCP Console 监控负载平衡、自动扩缩和托管的实例组。

    您可以使用 Compute Engine > 实例组部分来管理实例组和自动扩缩配置。

    您可以使用网络服务 > 负载平衡部分来管理负载平衡配置,包括网址映射和后端服务。

清理

为避免因本教程中使用的资源而导致系统向您的 Google Cloud Platform 帐号收取费用,请执行以下操作:

运行收尾清理脚本

如果您运行了 deploy.sh 脚本,请运行 teardown.sh 脚本以移除 deploy.sh 脚本创建的所有资源。这会将您的项目返回到运行 deploy.sh 脚本之前的状态,并有助于避免进一步计费。要移除在本教程开头部分创建的单个实例和存储分区,请按照下一部分中的说明进行操作。

手动删除资源

如果您手动执行本教程中的步骤,则可以手动删除您创建的云资源。

删除负载平衡器

  1. 在 GCP Console 中,转到“负载平衡”页面。

    转到“负载平衡”页面

  2. 点击要删除的负载平衡器旁边的复选框。

  3. 点击页面顶部的删除按钮,以删除该负载平衡器。

  4. 删除负载平衡器对话框中,选择关联的后端服务和运行状况检查资源。

  5. 点击删除负载平衡器按钮,以删除该负载平衡器及其关联资源。

删除 Compute Engine 托管实例组

要删除 Compute Engine 实例组,请运行以下命令:

  1. 在 GCP Console 中,转到“实例组”页面。

    转到“实例组”页面

  2. 点击要删除的实例组旁边的复选框。
  3. 点击页面顶部的删除按钮以删除实例组。

删除单个 Compute Engine 实例

要删除 Compute Engine 实例,请运行以下命令:

  1. 在 GCP Console 中,转到“虚拟机实例”页面。

    转到“虚拟机实例”页面

  2. 点击 要删除的实例旁边的复选框。
  3. 点击页面顶部的删除按钮以删除实例。

删除您的 Cloud Storage 存储分区

要删除 Cloud Storage 存储分区,请执行以下操作:

  1. 在 GCP Console 中,转到 Cloud Storage 浏览器。

    转到 Cloud Storage 浏览器

  2. 点击要删除的存储分区旁边的复选框。
  3. 点击页面顶部的删除按钮以删除存储分区。

后续步骤

此页内容是否有用?请给出您的反馈和评价:

发送以下问题的反馈:

此网页