With App Engine, you can build web applications that use Google's scalable infrastructure and services. App Engine runs your web application using a Java 8 JVM. App Engine invokes your app's servlet classes to handle requests and prepare responses in this environment.
Specifying the Java 8 runtime for your app
To make your app use the Java 8 runtime, add the following line
Note that existing App Engine applications that were previously using the Java 7 runtime will run in the Java 8 runtime simply by making that change.
The App Engine API for Java is represented by the
included with the App Engine SDK as part of the Cloud SDK
* represents the version of the API and the App Engine SDK).
You select the version of the API your application uses by including this JAR in the
WEB-INF/lib/ directory, or use Maven to handle dependencies. If a new
version of the Java runtime environment is released that introduces changes that
are not compatible with existing apps, that environment will have a new
major version number.
Using Maven to handle dependenciesYou can use Maven to manage all of the dependencies. For example, this
pom.xmlentry includes the latest App Engine API (
Rappengine-api-1.0-sdk) available from Maven Central:
<dependency> <groupId>com.google.appengine</groupId> <artifactId>appengine-api-1.0-sdk</artifactId> <version>1.9.77</version> </dependency>
The sandboxThe App Engine Java runtime distributes requests for applications across multiple web servers and prevents one application from interfering with another. An App Engine app must not respond slowly. A web request to an application must be handled within 60 seconds (10 minutes for TaskQueue requests). Processes that exceed this limit to respond are terminated to avoid overloading the web server.
Note that the only place where users can write files is the
/tmp will consume the memory allocated to your instance. The files
stored in this location are only available to this instance and only for the
lifetime of this specific instance.
The usual way for your application to get resource files is to package the files
you rely on with your application under
WEB-INF, then load them from your app
ServletContext.getResource(), or similar methods.
By default, all files in the WAR are "resource files". You can exclude files from
this set using the
Class loader JAR ordering
Sometimes, it might be necessary to redefine the order in which JAR files are
scanned for classes in order to resolve collisions between class names. In
these cases, loading priority can be granted to specific JAR files by adding a
<class-loader-config> element containing
<priority-specifier> elements in
appengine-web.xml file. For example:
<class-loader-config> <priority-specifier filename="mailapi.jar"/> </class-loader-config>
This places "
mailapi.jar" as the first JAR file to be searched for classes,
barring those in the directory
If multiple JAR files are prioritized, their original loading order (with
respect to each other) will be used. In other words, the order of the
<priority-specifier> elements themselves does not matter.
With the Java 8 runtime, you can create threads using App Engine's
and Java's built-in APIs, for example
Currently, if you want to call App Engine APIs (
you must call those APIs from a request thread or from a thread created using
the ThreadManager API.
An application can
- Create a thread factory by calling
- Call the factory's
newRequestThreadmethod, passing in the
newRequestThread(runnable), or use the factory object returned by
If you create a
must be explicitly called before the servlet request completes. Failing to do so
will cause the request to not complete and the app server to eventually fail.
Note that some libraries may create ThreadPoolExecutors for you.
An application can perform operations against the current thread, such as
Each request is limited to 50 concurrent App Engine API request threads.
When using threads, use high level concurrency
Runnable. Those take care of many of the subtle but
important details of concurrency like
and scheduling and
Supported build tools
To speed up your development process, you can use the App Engine plugins for Apache Maven or Gradle:
- Cloud SDK-based Apache Maven plugin
- Cloud SDK-based Gradle plugin.
- App Engine Java SDK-based Apache Maven plugin
Local development server
The development server runs your application on your local computer for development and testing. The server simulates the Datastore services. The development server can also generate configuration for Datastore indexes based on the queries the app performs during testing.
AppCfg is included with the standalone App Engine SDK for Java. It is a multipurpose tool that handles command-line interaction with your application running on App Engine. AppCfg can upload your application to App Engine, or just update the Datastore index configuration so you can build new indexes before updating the code. It can also download the app's log data, so you can analyze your app's performance using your own tools.
Concurrency and latency
Your application's latency has the biggest impact on the number of instances needed to serve your traffic. If you process requests quickly, a single instance can handle a lot of requests.Single-threaded instances can handle one concurrent request. Therefore, there is a direct relationship between the latency and number of requests that can be handled on the instance per second. For example, 10ms latency equals 100 request/second/instance.
Multi-threaded instances can handle many concurrent requests. Therefore, there is a direct relationship between the CPU consumed and the number of requests/second.
Java apps support concurrent requests, so a single instance can handle new requests while waiting for other requests to complete. Concurrency significantly reduces the number of instances your app requires, but you need to design your app for multithreading.
For example, if a B4 instance (approx 2.4GHz) consumes 10 Mcycles/request, you can process 240 requests/second/instance. If it consumes 100 Mcycles/request, you can process 24 requests/second/instance. These numbers are the ideal case but are fairly realistic in terms of what you can accomplish on an instance.