Microservices on Google App Engine

590 views
Skip to first unread message

Pim Reijersen

unread,
Nov 14, 2016, 10:47:53 AM11/14/16
to Google App Engine
Using the service (aka module) keyword in app.yaml its possible to create microservices on app engine.

The reason of this post is to get a better picture of how to setup an application existing of microservices on the app engine. The application in question will receive, store and send a good amount of data.


Microservices
Microservices communicate with eachother using HTTP requests. How do you decide where the service can be reached, and how does this translate to the development environment.
  1. Discovery service? Minimal sample or link?
  2. Hardcoded location <service>.<app_id>.appspot.com? and modify hosts file for local development?

Endpoints
  1. Is it a common practice to use the Endpoints feature to develop an API for internal communication between services?
    1. Another solution would be a webapp
  2. Is it a common practice to use the Endpoints feature to develop an REST API for users which communicates with the services?
    1. Another solution would be a webapp

Large response/request
Developing an application which receives/stores/distrubutes a large data set. Pushing and pulling data is done using a REST API. My concern is that the data travels to multiple services over the network increasing bandwith usage. Example;
[user] -> REST API Service -> Data Service -> Datastore

In a monolith application the data gets processed directly. In a microservice application the data travels from the user to the API Service and is then send to the Data Service to be processed.
  1. Give the Data Service an API which is accessible by the user?
  2. Is this an issue on App Engine cost wise?

Adam (Cloud Platform Support)

unread,
Nov 14, 2016, 7:38:19 PM11/14/16
to Google App Engine
Microservices:
  • You can target a specific service (aka module) directly using the URI scheme <service>.<appid>.appspot.com (or <service>.customdomain.tld). On the development server modules are served from different ports on localhost (eg. 8080 for default, 8081 for the next module).
  • In both production and on the development server, you can use dispatch rules to target requests to a specific service based on the URL pattern.
  • If using the Cloud Endpoints framework, API requests are sent to /_ah/spi/{path-to-method} (v1) or /_ah/api/{path-to-method} (v2) which can be targeted for routing different API calls with dispatch rules. There is an Endpoints discovery service, but this does not handle routing requests between services.

Endpoints:
  • Endpoints is intended as a REST API framework. It's technically possible to use it to communicate between services but there are some limitations such as not being able to call an Endpoints API from a task queue or cron job.
  • A better alternative to Endpoints for inter-service communication is Cloud Pub/Sub.

Large response/request:
  • Storage services such as Memcache, Datastore and Cloud Storage are shared across all services and version in a project. It's not necessary to pass data between services using URL endpoints as each service essentially has a fast path to access the same data on the internal network.
Let me know if I've missed anything or if you have further questions.

Pim Reijersen

unread,
Nov 15, 2016, 4:41:54 AM11/15/16
to Google App Engine
Hi Adam

Thanks for your quick response!

At the moment I have created a single App Engine project. Every module/service has its own repository with an app.yaml file.

<project-name>-service-api
- app.yaml
  * application: 123-<project-name>
  * module: default
- main.py

<project-name>-service-customer
- app.yaml
  * application: 123-<project-name>
  * module: <project-name>-service-customer
- main.py


Using this approach i'm capable of deploying every service independently, but it does give some issues with locks on the datastore. Looking at the limited resources I can find about this I'm having doubts about if this is the correct approach. It looks like people put every service/module in a single respository and define all the services/modules in a single app.yaml. What would be the correct approach?

Adam (Cloud Platform Support)

unread,
Nov 18, 2016, 1:06:02 PM11/18/16
to Google App Engine
To avoid the locking problem you'll want to create a separate .yaml file for each service in the same repository, as outlined in 'Configuration Files', and load all modules with the same dev_appserver.py instance. The default service .yaml doesn't have to be called 'app.yaml', but it does have to have either 'service: default' (or 'module: default', but 'service' is preferred) or have no service parameter specified.

You do not need to have the project name embedded in the service name (there's no need to repeat information). An example structure might look like this:

Directory: project-name/default
- app.yaml
 
* application: 123-<project-name>

 
* service: default
- main.py

Directory: project-name/service-customer
- app.yaml
 
* application: 123-<project-name>

 
* service: service-customer
- main.py

These would be launched from the dev server as:

$ appcfg.py default/app.yaml service/app.yaml <other .yaml files>

You could also have a flat directory structure, and use a different filename for the default service:

$ appcfg.py service-default.yaml service-customer.yaml <other .yaml files>

Adam (Cloud Platform Support)

unread,
Nov 18, 2016, 1:07:06 PM11/18/16
to Google App Engine
Errata: replace appcfg.py with dev_appserver.py in the command line examples.

Pim Reijersen

unread,
Nov 26, 2016, 9:15:37 AM11/26/16
to Google App Engine
Thank You Adam!

Most of my confusion was caused by using the App Engine launcher. Using the console commands you suggested I got it functional.

I do have a question remaining. Right now I have a directory structure like:
* service-note/app.yaml
* service-dashboard/app.yaml
* service-api/app.yaml

The third-party is making requests to the api service. However, let's assume that the request for note.create contains alot of data. Then I assume its better to dispatch to request directly to the note service.

When I create a dispatch.yaml and add it to the dev_appserver.py then a dispatch server is launched on another port then any of the services. So the usual of [service-api]/note.create won't work because the "service-api" is now a different host.

What would be the correct way to solve this issue?
Reply all
Reply to author
Forward
0 new messages