微服务 Rainbow Rumpus

1. 简介

上次更新日期:2021 年 5 月 6 日

微服务彩虹大乱斗

您是否曾参加过雪球大战,在其中四处移动,并向他人投掷雪球?如果还没有,不妨找个时间试试!不过,现在您不必担心被对方打到,可以构建一个小型、可通过网络访问的服务(微服务),让它参与到与其他微服务之间的史诗级战斗中,投掷彩虹而不是雪球。

您可能想知道…但微服务如何向其他微服务“抛出”彩虹呢?微服务可以接收网络请求(通常通过 HTTP)并返回响应。有一个“竞技场管理器”会向您的微服务发送竞技场的当前状态,然后您的微服务会以命令的形式做出响应,指定要执行的操作。

当然,目标是获胜,但在此过程中,您将了解如何在 Google Cloud 上构建和部署微服务。

运作方式

您将使用任意技术构建微服务(或从 Go、Java、Kotlin、Scala、NodeJS 或 Python 启动器中选择),然后在 Google Cloud 上部署该微服务。部署完成后,您需要告知我们微服务的网址,然后我们会将其添加到竞技场中。

竞技场包含指定战斗中的所有玩家。彩虹大乱斗将有自己的竞技场。每个玩家代表一个四处移动并向其他玩家投掷彩虹的微服务。

我们的竞技场管理器大约每秒会调用一次您的微服务,发送当前的竞技场状态(玩家所在的位置),而您的微服务会返回一个命令,指示该做什么。在竞技场中,您可以向前移动、向左或向右转,或者投掷彩虹。彩虹会朝玩家面向的方向移动最多 3 格。如果彩虹“击中”另一位玩家,投掷者得 1 分,被击中的玩家失 1 分。系统会根据当前玩家数量自动调整竞技场大小。

以下是过往竞技场的示例:

20628e6bd442bd11.png

示例竞技场 1

循环冲突

在竞技场中,可能会有多位玩家尝试执行冲突的操作。例如,两名玩家可能会尝试移动到同一格。如果发生冲突,响应时间最短的微服务胜出。

观看比赛

如需了解您的微服务在战斗中的表现,请查看实时竞技场!

Battle API

为了与我们的竞技场管理器配合使用,您的微服务需要实现一个特定的 API 才能参与竞技场。竞技场管理器将通过 HTTP POST 向您提供的网址发送当前竞技场状态,JSON 结构如下:

{
  "_links": {
    "self": {
      "href": "https://YOUR_SERVICE_URL"
    }
  },
  "arena": {
    "dims": [4,3], // width, height
    "state": {
      "https://A_PLAYERS_URL": {
        "x": 0, // zero-based x position, where 0 = left
        "y": 0, // zero-based y position, where 0 = top
        "direction": "N", // N = North, W = West, S = South, E = East
        "wasHit": false,
        "score": 0
      }
      ... // also you and the other players
    }
  }
}

您的 HTTP 响应必须是状态代码 200 (OK),并且响应正文包含您的下一步行动,编码为单个大写字符,可以是以下任一字符:

F <- move Forward
R <- turn Right
L <- turn Left
T <- Throw

就是这么简单!我们来逐步了解如何在 Cloud Run(一种用于运行微服务和其他应用的 Google Cloud 服务)上部署微服务。

2. 登录 Google Cloud

如需在 Cloud Run 上部署微服务,您需要登录 Google Cloud。我们会向您的账号发放赠金,您无需输入信用卡信息。使用个人账号(例如 gmail.com)通常比使用 GSuite 账号的问题更少,因为有时 GSuite 管理员会阻止其用户使用某些 Google Cloud 功能。此外,我们将使用的 Web 控制台应能与 Chrome 或 Firefox 完美搭配使用,但在 Safari 中可能会出现问题。

3. 部署微服务

您可以使用任何技术构建微服务,并将其部署在任何位置,只要该微服务可公开访问且符合 Battle API 即可。不过,为了方便起见,我们将帮助您从示例服务开始,并将其部署到 Cloud Run 上。

选择要从哪个示例开始

您可以从众多对战微服务示例入手:

Kotlin 和 Spring Boot

来源

Kotlin 和 Micronaut

来源

Kotlin 和 Quarkus

来源

Java 和 Spring Boot

来源

Java 和 Quarkus

来源

Go

来源

Node.js 和 Express

来源

Python 和 Flask

来源

确定要从哪个示例开始后,点击上方的“在 Cloud Run 上部署”按钮。此命令将启动 Cloud Shell(一个基于网络的云端虚拟机控制台),源代码将在其中克隆,然后构建为可部署的软件包(一个 Docker 容器映像),该软件包随后会上传到 Google Container Registry,然后部署到 Cloud Run。

当系统询问时,指定 us-central1 区域。

以下屏幕截图显示了微服务构建和部署的 Cloud Shell 输出

d88e40430706a32b.png

验证微服务是否正常运行

在 Cloud Shell 中,您可以向新部署的微服务发出请求,将 YOUR_SERVICE_URL 替换为您的服务的网址(该网址位于 Cloud Shell 中“Your application is now live here”这一行之后):

curl -d '{
  "_links": {
    "self": {
      "href": "https://foo.com"
    }
  },
  "arena": {
    "dims": [4,3],
    "state": {
      "https://foo.com": {
        "x": 0,
        "y": 0,
        "direction": "N",
        "wasHit": false,
        "score": 0
      }
    }
  }
}' -H "Content-Type: application/json" -X POST -w "\n" \
  https://YOUR_SERVICE_URL

您应该会看到 F、L、R 或 T 的响应字符串。

4. 申请加入竞技场

如要加入 Rainbow Rumpus,您需要加入竞技场。打开 rainbowrumpus.dev,点击竞技场中的“加入”,然后提供您的微服务网址。

5. 进行和部署更改

在进行更改之前,您需要在 Cloud Shell 中设置一些有关 GCP 项目和所用示例的信息。首先,列出您的 GCP 项目:

gcloud projects list

您可能只有一个项目。复制第一列中的 PROJECT_ID,并将其粘贴到以下命令中(将 YOUR_PROJECT_ID 替换为您的实际项目 ID),以设置一个环境变量,供我们在后续命令中使用:

export PROJECT_ID=YOUR_PROJECT_ID

现在,为所使用的示例设置另一个环境变量,以便在后续命令中指定正确的目录和服务名称:

# Copy and paste ONLY ONE of these
export SAMPLE=kotlin-micronaut
export SAMPLE=kotlin-quarkus
export SAMPLE=kotlin-springboot
export SAMPLE=java-quarkus
export SAMPLE=java-springboot
export SAMPLE=go
export SAMPLE=nodejs
export SAMPLE=python

现在,您可以在 Cloud Shell 中修改微服务的源代码。如需打开基于 Web 的 Cloud Shell 编辑器,请运行以下命令:

cloudshell edit cloudbowl-microservice-game/samples/$SAMPLE/README.md

然后,您会看到有关如何进行更改的进一步说明。

f910c9ef7b51c406.png

Cloud Shell,其中包含已打开示例项目的编辑器

保存更改后,使用 README.md 文件中的命令在 Cloud Shell 中启动应用,但首先要确保您位于 Cloud Shell 中的正确示例目录中:

cd cloudbowl-microservice-game/samples/$SAMPLE

应用运行后,打开新的 Cloud Shell 标签页,然后使用 curl 测试服务:

curl -d '{
  "_links": {
    "self": {
      "href": "https://foo.com"
    }
  },
  "arena": {
    "dims": [4,3],
    "state": {
      "https://foo.com": {
        "x": 0,
        "y": 0,
        "direction": "N",
        "wasHit": false,
        "score": 0
      }
    }
  }
}' -H "Content-Type: application/json" -X POST -w "\n" \
  http://localhost:8080

准备好部署更改后,在 Cloud Shell 中使用 pack 命令构建项目。此命令使用 Buildpack 检测项目类型、对其进行编译,并创建可部署的制品(一个 Docker 容器映像)。

# Make sure you are in a Cloud Shell tab where you set the PROJECT_ID
# and SAMPLE env vars. Otherwise, set them again.
pack build gcr.io/$PROJECT_ID/$SAMPLE \
  --path ~/cloudbowl-microservice-game/samples/$SAMPLE \
  --builder gcr.io/buildpacks/builder

现在,您的容器映像已创建完毕,请使用 docker 命令(在 Cloud Shell 中)将容器映像推送到 Google Container Registry,以便 Cloud Run 随后可以访问该映像:

docker push gcr.io/$PROJECT_ID/$SAMPLE

现在,在 Cloud Run 上部署新版本:

gcloud run deploy $SAMPLE \
          --project=$PROJECT_ID \
          --platform=managed \
          --region=us-central1 \
          --image=gcr.io/$PROJECT_ID/$SAMPLE \
          --allow-unauthenticated

现在,竞技场将使用您的新版本!

6. 在本地开发(可选)

您可以按照以下步骤使用自己的 IDE 在本地处理项目:

  1. [在 Cloud Shell 中] 将示例压缩为 ZIP 文件:
# Make sure the SAMPLE env var is still set. If not, re-set it.
cd ~/cloudbowl-microservice-game/samples
zip -r cloudbowl-sample.zip $SAMPLE
  1. [在 Cloud Shell 中] 将 ZIP 文件下载到您的计算机:
cloudshell download-file cloudbowl-sample.zip
  1. [在您的机器上] 解压缩文件,然后进行更改并对其进行测试
  2. [在您的机器上] 安装 gcloud CLI
  3. [在您的机器上] 登录 Google Cloud:
gcloud auth login
  1. [在您的机器上] 将环境变量 PROJECT_ID 和 SAMPLE 设置为与 Cloud Shell 中相同的值。
  2. [在您的机器上] 使用 Cloud Build 构建容器(从根项目目录中):
gcloud alpha builds submit . \
  --pack=image=gcr.io/$PROJECT_ID/$SAMPLE \
  --project=$PROJECT_ID
  1. [在您的机器上] 部署新容器:
gcloud run deploy $SAMPLE \
  --project=$PROJECT_ID \
  --platform=managed \
  --region=us-central1 \
  --image=gcr.io/$PROJECT_ID/$SAMPLE \
  --allow-unauthenticated

7. 持续交付

设置 SCM

设置 GitHub,以便您与团队协作开发微服务:

  1. 登录 GitHub
  2. 创建新代码库
  3. 如果您使用的是本地机器,则可以使用 Git 命令行界面 (CLI) 或 GitHub Desktop GUI 应用(Windows 或 Mac)。如果您使用的是 Cloud Shell,则必须使用 git CLI。如需在 GitHub 上获取微服务的代码,请按照 CLI 或 GitHub Desktop 说明操作。

使用 Git CLI 推送代码

  1. 按照使用个人访问令牌通过 HTTPS 访问 Git 的说明操作
  2. 选择“代码库”范围
  3. 设置 Git:
git config --global credential.helper \
  'cache --timeout=172800'
git config --global push.default current
git config --global user.email "YOUR@EMAIL"
git config --global user.name "YOUR NAME"
  1. 为 GitHub 组织和代码库设置环境变量 (https://github.com/ORG/REPO)
export GITHUB_ORG=YOUR_GITHUB_ORG
export GITHUB_REPO=YOUR_GITHUB_REPO
  1. 将代码推送到新仓库
# Make sure the SAMPLE env var is still set. If not, re-set it.
cd ~/cloudbowl-microservice-game/samples/$SAMPLE
git init
git add .
git commit -m init
git remote add origin https://github.com/$GITHUB_ORG/$GITHUB_REPO.git
git branch -M main

# This will now ask for your GitHub username & password
# for the password use the personal access token
git push -u origin main
  1. 进行任何更改后,您可以提交并将更改推送到 GitHub:
git add .
git status
git diff --staged
git commit -am "my changes"
git push

使用 GitHub Desktop 推送代码

  1. 按照上一个“在本地开发”实验中的说明下载代码
  2. 安装 GitHub Desktop,启动该应用并登录
  3. 克隆您新创建的代码库

cf7f38c7c86a91cd.png

  1. 打开文件资源管理器,然后将项目复制到新代码库中
  2. 提交更改

5f3c1552e30ad7c5.png

  1. 将主分支发布到 GitHub

设置 Cloud Run 持续部署

在 GitHub 上设置 SCM 后,您现在可以设置持续交付,以便每次将新提交推送到 main 分支时,Cloud Build 都会自动构建和部署更改。您还可以添加在部署之前运行测试的持续集成,但由于现成的示例不包含任何测试,因此此步骤留给您自行练习。

  1. 在 Cloud 控制台中,前往您的 Cloud Run 服务
  2. 点击“设置持续部署”按钮
  3. 使用 GitHub 进行身份验证,然后选择微服务的代码库

a3b5692f178869bc.png

  1. 选择您的 GitHub 代码库,并将分支设置为:^main$

338f1c00f33d2f65.png

  1. 将 build 类型设置为使用 Buildpack
  2. 点击“保存”以设置持续部署。

8. 可观测性

世事难料。可观测性使我们能够知道何时发生这种情况,并诊断原因。指标会显示有关我们服务运行状况和使用情况的数据。日志会显示从服务中手动插桩的信息。通过提醒,我们可以在出现问题时收到通知。下面我们来进一步了解这些功能。

指标

  1. 在 Cloud Run 服务列表中找到您的服务
  2. 点击服务的名称,即可访问其指标信息中心

8491b8ec6bc5b4db.png

  1. 点击指标的 ⋮ 菜单,然后选择“在 Metrics Explorer 中查看”
  2. 现在,您可以更改资源指标、过滤条件、分组和其他选项。例如,您可以查看所有服务的平均服务延迟时间:

f0d666d8f4221d45.png

日志

来自服务的 STDOUT 输出会发送到 Google Cloud Logging 系统。您可以在 Cloud Run 服务管理页面中访问基本日志视图,例如:

40058a82c9299cff.png

在 Cloud Run 日志中,您可以按严重程度过滤日志。如需更灵活的方案,请点击:186fdb0e6d39a6ca.png

提醒

  1. 为您的服务创建健康检查网址。
  2. 对于 Spring Boot,只需添加以下依赖项:
org.springframework.boot:spring-boot-starter-actuator
  1. 创建或更新 src/main/resources/application.properties 并停用磁盘空间检查:
management.health.diskspace.enabled=false
  1. 创建正常运行时间提醒,指定您的协议、主机名和路径。对于 Spring Boot,路径为:/actuator/health
  2. 测试提醒

6948d13b263bf573.png

  1. 创建提醒

9. 恭喜

恭喜!您已成功构建并部署了一个可以与其他微服务对战的微服务!祝您好运!

参考文档