Understanding Google App Engine runtimes

This years second generation of standard runtimes for Google App Engine was released. So now there is First and Second generations of Standard and also Flexible. For people who are coming to Google Cloud Platform and are thinking about using Google App Engine this can be confusing, so with this article I wanted to bring maybe bit more clarification. It can be also nice nostalgia reading for long time users. 

History & Philosophy

First chapter

It has been 10 years since Google App Engine was launched. This way Google entered into Cloud area. Based on intro post promise of App Engine was simple: "Google App Engine gives you access to the same building blocks that Google uses for its own applications, making it easier to build an application that runs reliably, even under heavy load and with large amounts of data." in other words write code and Google will take care of everything else like it does for it self: scalability, deployment, load balancing, security, as well as other services directly included like Memcache, Taskqueues, NoSQL database. It offered SDK which could be used for local development and which mimics behavior as in production.

With GAE introduction, Google shared it's own app development workflow at the time with the rest of the world. First supported language was Python and in 2009 Java followed. Through years other languages and services on GAE as well as other products like Cloud Storage or Cloud SQL were introduced which eventually led to formation of Google Cloud Platform.

I wasn't there since beginning but later whenever I read some discussion on internet (typically on Hacker News) number one complaint about GAE was vendor lock-in. That means that the code you for wrote for GAE applications could be very GAE specific (use of internal GAE APIs), in other words if you would like to migrate off GAE that would meant major code rewrites (depending on the GAE services used). Because of that, some people ignored GAE, some people started using GAE, growing apps but then stuck on hindrances which GAE by it's nature implies like usage of some libraries or language restriction. For a lot of people GAE tooling offered web app developer's dream, since they didn't have to worry about ops, they could write code, run/debug locally and then with one command deploy. 

Integrated services to which I am and will be reffering through the rest of the article and which are available in First Generation runtime are:

  • Datastore - NoSQL database
  • Memcache - in memory cache
  • Search - service for indexing and searching text data
  • Task Queue - asynchronous executions of tasks
  • Cron - running jobs periodically
  • URL Fetch - making HTTP requests
  • Users - Detecting logged in users
  • Capabilities - detecting outages and scheduled downtimes for specific services like Datastore, Mail, Memcache etc.
  • Multitenancy (Namespaces API) - support for multi tenancy in several services
  • Mail - sending / receiving emails
  • App Identity - application id (or project id) discovery
  • Images - different image operations like rotation, resizing, flipping etc.
  • Blobstore - storing data blobs 
  • Services - microservice support

Maybe I didn't list all of them, some were in the meantime deprecated, full list with past and ongoing deprecations is here https://cloud.google.com/appengine/docs/deprecations/. I'm not sure if all of these services are supported for all First Generation languages. 

Second chapter

Few years afterwards Docker and "Container revolution" came and somewhere in 2014 Google introduced GAE Flexible. Idea was to remove limitations of GAE Standard with keeping existing services. In Beta release only some GAE services were working but they were removed completely with general availability, so there was just pure runtime with no other internal dependencies and no restrictions. I wrote my thoughts regarding that some time ago here and here. Additional advantage of GAE Flexible is use of custom VM setup for number of CPUs and RAM as well as lower price in comparison with GAE Standard.

Biggest differences between GAE Standard and Flex is that Flex runs on real Compute Engine VMs and that always needs to be minimum of 1 running instance and starting new server instance is way slower than in GAE Standard since it takes longer time to boot up server. With this you can deploy either prebuild Docker image for several languages, or you can deploy your own Docker image as long as it listens and makes response to port 8080. 

Third chapter

In spring 2018 so called Second Generation of GAE Standard was introduced with initial NodeJS support. It's built on top of gVisor which is Google's open source project which includes runtime which provides an isolation boundary between the application and the host kernel. In other words it provides sandbox environment / additional isolation which containers don't and it's simpler to lunch instances/containers than in First Generation where each language needed to have custom cuts and restrictions. So basically with gVisor Google improves solution of security issues so now it's quite straightforward to add different runtimes. So far Python 3.7, Go 1.11, Java 8, PHP 7.2, NodeJS 10 are supported.

GAE Second Generation runtimes are mix of First generation and Flexible: they offer scalability properties of First generation with no system / library constraints of Flexible. So finally criticts of First Generation vendor lock have no excuse to use App Engine :) Second generation runtime doesn't support though services of First Generation which for some there is no simple alternative or to access different products and services, everything needs to be done through client libraries. I was part of alpha preview for Second Generation of Python 3.7 and the loudest cry there (from long time / hard core users) was because of missing integrated services. Great news is that Google has already done some steps to improve that with several standalone / independent products:

  • Cloud Tasks - a.k.a GAE Taskqueues, allow possibility to run longer jobs, at the moment workers are running only on GAE (it's basically copy of GAE Taskqueues) but probably other compute options will be added. Of course system is scalable, supporting retry options, execution scheduling, multiple queues. 
  • Cloud Scheduler - a.k.a GAE Cron, offers possibility to execute various jobs with cron like time executing definitions. It's great that initially beside GAE two additional targets are supported: Pub/Sub (publishing to topic) and URL (fetching url with various HTTP methods and defined body)
  • Cloud MemoryStore - managed Redis database which is also often used for caching. This doesn't replace for 100% Memcache service on GAE First Generation since price starts at 36$ and so far can be used only on GAE Flexible. In official documentation there is also recommendation of Redis Labs Cloud

 

Here is table which summarizes most important properties and differences.

 

RuntimeStandard First GenenerationStandard Second GenerationFlexible

Supported Languages

Python 2.7,
Go
Java 7
PHP 5.5
Python 2.7,
Go 1.11,
Java 8,
PHP 7.2,
Nodejs 8, 10
Python 2.7, 3.6,
Go 1.9, 1.10, 1.11,
Java 8, 9,
PHP 5.6, 7.0, 7.1, 7.2
Ruby
.NET
custom Docker image
RestrictionsEvery supported language 
has different constraints
regarding third party
libraries
 No restrictions No restrictions
Background threads / processesNoNoYes
Maximum request timeout60 seconds60 seconds60 minutes

Scalability
(new instance creation) 

Fast, order of seconds

Fast, order of secondsSlow, order of minutes

Minimum running
instances

001
Instance types

from 600MHz, 128MB

to 4.8GHz, 1024MB

from 600MHz, 128MB

to 4.8GHz, 1024MB

from 1 vCPU 0.9 GB
to 32 vCPUs, 149.5GB
where vCPU is implemented
as a single hardware
hyper-thread
Cost/Pricing

from 0.05$/hour
to 0.3$/hour

(one instance for free)

from 0.05$/hour

to 0.3$/hour

(one instance for free)

0.063$ per vCPU/hour
0.009$ per GB RAM/hour
0.048$ per GB disk/month
min 10GB of disk

  

When to use which runtime (for new project)?

  • First & Second Generation: you are working on some personal prototype or starting from scratch and you want to take advantage of scaling to zero and one always free instance. Depending on traffic you can have basically running app for free. If you have some application with First generation and you need to add functionality which requires library which is not possible to use on GAE First generation, now with Second generation you can extend your existing application with microservice like architecture where you can deploy web app to run code which you couldn't run on GAE Standard.
    • Standard First Generation: If you are long time hard code GAE user, it's hard for you to use anything other than integrated GAE services. Or you're doing small one time project with definite idea about scope, usage and functionality. You don't mind using older languages and you are not constrained by GAE limitations regarding third party libraries. 
    • Standard Second Generation: You are not so stick in First Gen mentality (or you are new GAE user) and you want to use newest language versions and it's not problem for you to use client libraries to access other GCP products. In other words, Standard Second Generation should be default. 
  • Flexible: You have some very specific use case where you can take advantage of bigger machines for some intensive processing and maybe you are doing it in some exotic language which you deployed through Docker container. Maybe not the best solution for pet project since at the start cost of running 1 instance (1CPU/1 GB RAM) is starting from 52$/month. Also need to be careful when deploying new version, previous one isn't stopped so then you can have multiple versions running which can easily multiple costs. Also if you have already your app in Docker container, it's much easier to move it somewhere else, like for example Google Kubernetes Engine.

Few times in article I mentioned combining different runtimes in one project. This functionality is provided via Services - GAE microservice support. In other words, it's possible to deploy multiple GAE applications with independant runtimes, languages, configurations, versions which improves whole scalability and reliability. 

Last advice: check if other GCP products can be used with your runtime and what kind of support there is within client libraries for other products (to have life simpler).

 

blog comments powered by Disqus