Last Updated: 2020-08-26

Microservices Battle Arena

Ever been in a snowball fight where you move around and playfully throw snowballs at others? If not, try it someday! But now instead of risking getting physically smacked, you can build a small, network accessible service (a microservice) that will take part in an epic battle against other microservices. And since we are hosting this microservice battle at SpringOne, our microservices will be throwing leaves instead of snowballs.

You might be wondering... But how does a microservice "throw" a leaf at other microservices? A microservice can receive network requests (usually over HTTP) and return responses. There is an "arena manager" that will send your microservice the current state of the arena and then your microservice will respond with a command specifying what to do.

Of course the goal is to win, but along the way you'll learn about building and deploying microservices on Google Cloud.

How It Works

You will build a microservice with any technology you want (or choose from Java, Kotlin, or Scala starters) and then deploy the microservice on Google Cloud. Once deployed, you'll fill out a form to let us know the URL for your microservice and then we will add it to the arena.

The arena contains all of the players for a given battle. The SpringOne conference will have its own arena. Each player represents a microservice that moves around and throws leaves at the other players.

About once a second our arena manager will call your microservice, sending the current arena state (where the players are), and your microservice will respond with a command for what to do. In the arena you can move forward, turn left or right, or throw a leaf. A thrown leaf will travel up to three spaces in the direction the player is facing. If a leaf "hits" another player, the thrower gets one point and the hit player loses a point. The arena size is auto-adjusted for the current number of players.

Here is how a past arena looks:

Example Battle One arena

Revolving Conflicts

In the arena it is possible that multiple players try to perform conflicting actions. For instance, two players might try to move to the same space. In the case of a conflict, the microservice with the quickest response time wins.

Watching the Battle

To see how your microservice is doing in the battle, check out the live arena!

Battle API

In order to work with our arena manager, your microservice will need to implement a specific API to participate in the arena. The arena manager will send the current arena state in an HTTP POST to the URL you provide us, with the following JSON structure:

{
  "_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
    }
  }
}

Your HTTP response must be status code 200 (OK) with a response body containing your next move, encoded as a single uppercase character of either:

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

That's all there is to it! Let's walk through deploying a microservice on Cloud Run, a Google Cloud service for running microservices and other applications.

To be able to deploy your microservice on Cloud Run you will need to login to Google Cloud. We will apply a credit to your account and you won't need to enter a credit card. It is usually less problematic to use a personal account (e.g. gmail.com) instead of a GSuite account because sometimes GSuite admins prevent their users from using certain Google Cloud features. Also, the web console we will be using should work great with Chrome or Firefox but might have issues in Safari.

Get started and login

You can build your microservice with any technology and deploy it anywhere as long as it is reachable publicly and conforms to the Battle API. But to make things easy we will help you start from a sample service and deploy it on Cloud Run.

Pick Your Sample To Start With

There are two battle microservice samples you can start from:

Java & Spring Boot

Source

Deploy on Cloud Run

Kotlin & Spring Boot

Source

Deploy on Cloud Run

After you decide which sample to start with, click the "Deploy on Cloud Run" button above. This will launch Cloud Shell (a web-based console to a virtual machine in the cloud) where the source will be cloned, then built into a deployable package (a docker container image), which is then uploaded to the Google Container Registry, and then deployed on Cloud Run.

When asked, specify the us-central1 region.

The screenshot below shows Cloud Shell output for microservice build and deployment

Verify the microservice works

In Cloud Shell you can make a request to your newly deployed microservice, replacing YOUR_SERVICE_URL with the URL for your service (which is in Cloud Shell after the "Your application is now live here" line):

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

You should see the response string of either F, L, R, or T.

To be included in the arena you need to send a message to the #3-sponsor-google-cloud Slack channel with your name, Cloud Run service URL, and optionally your GitHub username for its avatar / profile photo. Once we validate the information, your player will appear in the arena.

Before you can make changes you need to setup some information in Cloud Shell about the GCP project and the sample you used. First list your GCP projects:

gcloud projects list

You likely only have one project. Copy the PROJECT_ID from the first column and paste it into the following command (replacing YOUR_PROJECT_ID with your actual Project ID), in order to set an environment variable that we will use in later commands:

export PROJECT_ID=YOUR_PROJECT_ID

Now set another environment variable for the sample you used so in later commands we can specify the correct directory and service name:

# Copy and paste ONLY ONE of these
export SAMPLE=java-springboot
export SAMPLE=kotlin-springboot

Now, you can edit the source for your microservice from within Cloud Shell. To open the Cloud Shell web-based editor, run this command:

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

You will then see further instructions for making changes.

Cloud Shell with the editor with the sample project open

After saving your changes, start the application in Cloud Shell:

cd cloudbowl-microservice-game/samples/$SAMPLE
./mvnw spring-boot:run

Once the application is running, open a new Cloud Shell tab and test the service using 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

When you are ready to deploy your changes, build your project in Cloud Shell using the pack command. This command uses Buildpacks to detect the project type, compile it, and create the deployable artifact (a docker container image).

pack build gcr.io/$PROJECT_ID/$SAMPLE \
  --path ~/cloudbowl-microservice-game/samples/$SAMPLE \
  --builder gcr.io/buildpacks/builder

Now that your container image has been created, use the docker command (in Cloud Shell) to push the container image to the Google Container Registry so that it can then be accessed by Cloud Run:

docker push gcr.io/$PROJECT_ID/$SAMPLE

Now deploy the new version on Cloud Run:

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

Now the arena will use your new version!

You can work on your project locally using your own IDE by following these steps:

  1. [In Cloud Shell] Zip up the sample:

cd ~/cloudbowl-microservice-game/samples; zip -r cloudbowl-sample.zip $SAMPLE

  1. [In Cloud Shell] Download the zip file to your machine:

cloudshell download-file cloudbowl-sample.zip

  1. [On your machine] Unzip the file and then make & test your changes
  2. [On your machine] Install the gcloud CLI
  3. [On your machine] Login to Google Cloud:

gcloud auth login

  1. [On your machine] Set the environment variables PROJECT_ID and SAMPLE to the same values as in Cloud Shell.
  2. [On your machine] Use Cloud Build to build the container (from the root project directory):

gcloud alpha builds submit . --pack=image=gcr.io/$PROJECT_ID/$SAMPLE

  1. [On your machine] Deploy the new container:

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

Congratulations, you've successfully built and deployed a microservice that can battle with other microservices! Good luck!

Continue Learning

Reference Docs

Why isn't my microservice showing up in the arena?