DEV Community

DrBearhands
DrBearhands

Posted on

Microservices on Google App Engine

This post is as much a rant as it is a guide. Things seem to take 10 times as long when I'm relying on Google's documentation. So while everything I'm about to describe sounds too simple to warrant a guide, I've decided to make one anyway. Hopefully this will save someone else a lot of time.

So here it is, how to deploy microservices, each with their own subdomain, using Google App Engine.

This guide assumes that you can already deploy an app on Google Cloud Platform.

Note that if you use App Engine Flexible, you will have to pay for resources to keep each service running, separately.

Introduction & motivation

I'm creating a websites that scrapes IT jobs, does some analysis on them and makes the results searchable. It has an SPA written in Elm (compiles to js) and an API/backend in Go that serves job results from the database.

For a while, I essentially compiled the frontend into a /public subdirectory of my backend. Using the backend as both an API and static file server. This setup caused a number of issues, mostly with my build/deploy pipeline. While these issues could have been fixed individually, I'd much rather fix the underlying problem. What's more, some future features I'd planned would also have benefited from the change.

So I decided to separate my backend and frontend into (micro)services.

Creating services

I've briefly mentioned creating services in my previous post about low-cost periodic tasks on Google Compute Engine.
A service is just like any other app and you create it in the same way. Actually an app is already a service, the default service. To deploy your app as a different service, just add a service: <service name> line in you app.yaml file.

With that line added, gcloud will deploy your application as a non-default service. Service names are unique on a per-project basis.

For your frontend, you might only have static files (I did). In this case, you can use a similar app.yaml file:

runtime: python27
api_version: 1
threadsafe: true

handlers:
    - url: /
      static_files: build/index.html
      upload: build/index.html

    - url: /*
      static_dir: build

This will serve static files from the ./build directory, relative to your app.yaml file.

Note that the runtime is important, if you specify e.g. go as the runtime, your application will not function as it won't be able to find a go program to run. python27 allows you to not have an app running.

Custom (sub)domains

I'll be assuming you want to use your own domain name rather than relying on the standard appspot.com domain provided by Google. For the base domain this is actually relatively well-explained in Google's own documentation.

The documentation also mentions the possibility of registering a wildcard * subdomain, and how requests will automatically be forwarded to a service with the same name. Unfortunately wildcard domains cannot have auto-managed ssl certificates. This is a major drawback, so we will be using explicit subdomains instead.

First, register them as explained in the documentation. There's a caveat here and that's DNS changes propagation. Even though the changes you made in your DNS records might have propagated far enough for you to visit the site, they may not have propagated far enough for google's ssl certificate generation. This means you might be able to connect to your website through http but not https. If that's the case, just go do something else and come back the next day or so.

When this is done, visiting any of your registered subdomains should land you on the default service of your project.

Next, we're going to map the domains to specific services. This is actually rather simple, but the documentation seems to only mention it in relation to wildcard subdomains. Just create a dispatch.yaml file. This is a file defining any non-default routing of URLs and domains for the entire project. E.g., my dispatch.yaml looks like this:

dispatch:
  - url: "jobs.jobsort.io/*"
    service: jobs

As you can see I've not listed the default service. This is not necessary as it all registered domains are routed to the default service unless otherwise specified.

You can deploy the dispatch.yaml file using a terminal: gcloud app deploy dispatch.yaml.

Concluding comments

Still missing from this guide is how to run your project, which is now comprised of microservices, locally. This is a bit beyond the scope of this post and frankly I haven't found a system that I like 100%. I will endeavor to write a guide about that in the future.

Discussion (0)