What Google App Engine does
As mentioned earlier, App Engine is a PaaS, which means that we have the benefits of SaaS products but with an augmented flexibility as we have complete control over the code. We also have the benefits of an IaaS solution but without the hassle of maintaining and configuring the software environment needed to run applications on a raw hardware system.
Developers are the favored users of a PaaS product such as App Engine because the platform helps them in two ways: it provides an easy way to deploy, scale, tune, and monitor web applications without the need for a system administrator and it offers a set of tools and services that speed up the software development process. Let's explore these two aspects in detail.
The runtime environment
App Engine runs on computing units that are completely managed called instances. We can (and should) ignore which operating system is running on an instance because we interact solely with the runtime environment, which is an abstraction of the operating system that provides resource allocation, computation management, request handling, scaling, and load balancing.
Note
Developers can choose among four different programming languages to write applications on App Engine: Python, Java, Hypertext Preprocessor (PHP), and Go but we will focus on the Python environment.
Every time a client contacts an application that runs on App Engine, a component of the runtime environment called scheduler selects an instance that can provide a fast response, initializes it with application data if needed, and executes the application with a Python interpreter in a safe, sandboxed environment. The application receives the HTTP request, performs its work, and sends an HTTP response back to the environment. Communication between the runtime environment and the application is performed using the Web Server Gateway Interface (WSGI) protocol; this means that developers can use any WSGI-compatible web framework in their application.
Tip
WSGI is a specification that describes how a web server communicates with web applications written in Python. It was originally described in PEP-0333 and later updated in PEP-3333, mainly to improve usability under the Python 3.0 release.
The runtime environment is sandboxed to improve security and provide isolation between applications running on the same instance. The interpreter can execute any Python code, import other modules, and access the standard library, provided that it doesn't violate sandbox restrictions. In particular, the interpreter will raise an exception whenever it tries to write to the filesystem, perform network connections, or import extension modules written in the C language. Another isolation mechanism we must be aware of that is provided by sandboxing, prevents an application from overusing an instance by raising an exception whenever the entire request/response cycle lasts more than 60 seconds.
Thanks to sandboxing, the runtime can decide at any given time whether to run an application on one instance or many instances, with requests being spread across all of them depending on the traffic. This capability, together with load balancing and scheduler settings is what makes App Engine really scalable.
Users can easily tune an application's performance by increasing its responsiveness or optimizing costs with a simple and interactive administrative console. We can specify instance performance in terms of memory and CPU limits, the number of idle instances always ready to satisfy a request, and the number of instances dynamically started when the traffic increases. We can also specify the maximum amount of time in milliseconds we tolerate for a pending request and let App Engine adjust the settings automatically.
The services
At first sight, restrictions imposed by the runtime environment might seem too restrictive. In the end, how can developers make something useful without being able to write data on disk, receive incoming network connections, fetch resources from external web applications, or start utility services such as a cache? This is why App Engine provides a set of higher-level APIs/services that can be used by developers to store and cache data or communicate over the Internet.
Some of these services are provided by the Google Cloud Platform as standalone products and are smoothly integrated into App Engine, while some others are only available from within the runtime environment.
The list of available services changes quite often as Google releases new APIs and tools; the following is a subset of tools we will use later in the book in addition to the Datastore, Google Cloud Endpoints, Google Cloud SQL, and Google Cloud Storage services we introduced earlier:
- Channel: This API allows applications to create persistent connections with the clients and push data through such connections in real time instead of using polling strategies. Clients must use some JavaScript code to interact with the server. We will learn how to use Channels in Chapter 6, Using Channels to Implement a Real-time Application.
- Datastore backup/restore: At any given time, it's possible to perform a backup of the entities contained in the Datastore or restore them from a previous backup; management operations are very easy as they can be performed interactively from the administrative console. We will see backup and restore procedures in detail in Chapter 4, Improving Application Performance.
- Images: This API lets developers access and manipulate image data provided by the application or loaded from Google Cloud Storage. We can get information about the format, size, and colors and perform operations such as resizing, rotating, and cropping and we can convert images between different formats and apply some basic filters provided by the API. We will use some of the features provided by the Images API in Chapter 3, Storing and Processing Users' Data.
- Mail: This service allows applications to send e-mails on behalf of the administrators or users who are logged in with a Google Account and to receive e-mail messages sent to certain addresses and routed to the application. We will use both these features provided by the service in Chapter 3, Storing and Processing Users' Data.
- Memcache: This is a general-purpose, distributed memory caching system that can be used to dramatically improve application performance, serving frequently accessed data way faster than accessing a database or an API. We will see how to use Memcache in Chapter 4, Improving Application Performance.
- Modules: These are used to split applications into logical components that can communicate and share their state with each other. They can be extremely useful as each of them can have different versions and performance and scaling settings, which provide developers with a great level of flexibility when tuning an application. We will see how to use Modules in Chapter 4, Improving Application Performance.
- Scheduled tasks: This is how App Engine implements the cron jobs. Developers can schedule a job to be executed at a defined date or at regular intervals. Schedules are defined in an English-like format: for example,
every Friday 20:00
is a valid schedule we can use to send weekly reports to our users. We will see how to use scheduled tasks in Chapter 3, Storing and Processing Users' Data. - Task Queue: As mentioned earlier, the entire request/response cycle of an application running on App Engine must last at most 60 seconds, making it impossible to perform long operations. This is why the Task Queue API exists––it can perform work outside the user request so that long operations can be executed later in background with 10 minutes to finish. We will see how to use a task queue in Chapter 3, Storing and Processing Users' Data.
- URL Fetch: As we already know, the runtime environment prevents our application from performing any kind of network connection but accessing external resources through HTTP requests is a common requirement for a web application. This limitation can be overcome using the URL Fetch API to issue HTTP or HTTPS requests and retrieve a response in a scalable and efficient manner.
- Users: We can authenticate users within our applications using Google Accounts, accounts in a Google Apps domain, or through OpenID identifiers. Using the Users API our application can determine whether a user is logged in and redirect them to the login page or access their e-mail otherwise. Using this API, developers can delegate to Google or to the OpenID provider the responsibility of creating accounts and verifying the user's data.
For more information on the tools and services provided by Google that we can use from within the App Engine environment, refer to https://developers.google.com/appengine/features/.