11.4. Backends
So far, App Engine handled file upload, cache ops and task execution through a default frontend instance. This instance has 60 seconds deadline for HTTP requests and 10 minutes deadline for tasks and a low memory cap of 128MB.
App Engine Backends allows us to configure additional instances to overcome these limits. App Engine Backends are special instances that have no request deadlines and comes with higher memory and CPU limits, and provides persistent state across requests. We may configure Backends to access more memory (up to 1GB) and CPU (up to 4.8GHz).
Google App Engine Backends
In this section, we move GaePersistTask
to a Backend. But before
that, let’s understand the concept of Backend with a servlet example.
Normally GAE runs the app on default instance. Backends are additional instances of the app. These additional instances are exact replica of the default instance. To understand this, add a test servlet to the app.
in.fins.server.task/TestServlet.java
public class TestServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// Get the backend handling the current request.
BackendService backendsApi = BackendServiceFactory.getBackendService();
String currentBackendName = backendsApi.getCurrentBackend();
PrintWriter out = resp.getWriter();
out.println("Backend Name : " + currentBackendName);
}
}
TestServlet obtains the name of current backend through Backend API and sends it as response to the browser.
Add servlet entry to web.xml
with url-pattern as
/testServlet. Deploy the app and access the servlet with
http://yourappname.appspot.com/testServlet
. App Engine sends a
response Backend Name : null, which indicates that servlet is executed
on default instance.
Next configure a backend by adding backends.xml to the app
war/WEB-INF/backends.xml
<?xml version="1.0" encoding="utf-8"?>
<backends>
<backend name="test-backend">
<class>B2</class>
<options>
<dynamic>true</dynamic>
<public>true</public>
</options>
</backend>
</backends>
Deploy the app to App Engine. Now, in addition to default instance, App Engine starts a backend instance and you may access the TestServlet with following URL.
http://yourappname.appspot.com/testServlet
- TestServlet runs on default instance and sends response as Backend Name : nullhttp://test-backend.yourappname.appspot.com/testServlet
- TestServlet runs on test-backend Backend Instance and sends response as Backend Name : test-backend
Even though we are able to run servlets (or other classes) on backends, appropriate use of backends is with GAE services like Task Queues, Cron jobs etc.,
Once you are through with the concept, remove TestServlet related
changes from the project and we are ready to move GaePersistTask
to
Backend.
Configure Backend
Backend configuration file, WEB-INF/backends.xml
, configures and adds
backend instances.
war/WEB-INF/backends.xml
<backends>
<backend name="task-backend">
<class>B2</class>
<options>
<dynamic>true</dynamic>
<public>false</public>
</options>
</backend>
</backends>
With this config file, App Engine creates a backend named task-backend. App Engine allows four classes of Backends, B1, B2, B4 and B8 and Class B2 has Memory limit is 256MB, CPU limit 1200MHz.
Backend may be resident or dynamic. Resident backends run continuously where state is maintained over a long period of time while Dynamic backends come into existence when they receive a request, and are teared down when idle. Persist task doesn’t require a resident backend as the activity is intermittent in nature without any dependence on state information. Hence, task-backend is configured as dynamic.
Persistence task runs in the background and requires no public access. Hence task-backend is configured as a private backend.
Run Task on Backend
Once Backend is configured, we may obtain its address through Backend API.
String backendAddress = BackendServiceFactory.getBackendService()
.getBackendAddress("task-backend");
Backend address is added to Task URL header, which forces the App Engine to execute the task on a specific Backend.
in.fins.server.task/GaePersistTask.java
@Override
public void execute(Map<String, Object> parameters) throws Exception {
....
String backendAddress = BackendServiceFactory.getBackendService()
.getBackendAddress("task-backend");
TaskOptions task = withUrl("/fins/gaePersistTask")
.param("symbolName", symbolName).method(Method.POST)
.header("Host", backendAddress);
Queue queue = QueueFactory.getQueue(qName);
queue.add(task);
}
In development mode, server may throw ConnectException
and fails to
bring up the Backend.
INFO: Retrying request
May 25, 2013 6:46:44 PM com.google.appengine.tools.development.AbstractBackendServers$ServerWrapper sendStartRequest
WARNING: Got exception while performing /_ah/start request on server: 0.task-backend, java.net.ConnectException: Connection refused
It is found that disabling the net connection before launching the application or reloading the server, may solve the issue. Doing so brings up Backend on some free port.
May 26, 2013 11:10:09 AM com.google.appengine.tools.development.AbstractBackendServers$ServerWrapper startup
INFO: server: -1.task-backend is running on port 47589
May 26, 2013 4:40:09 PM com.google.appengine.tools.development.DevAppServerImpl start
INFO: Dev App Server is now running
If this workaround fails to bring up the Backend, then only option is to test Backends on live setup.
Admin console has options to manage the Backends instances.
In the next section, we list the steps to switch the app to run on regular app servers.
Forward Pointers
App Engine Services - Details about various service provided by App Engine Java Service APIs
Memcache - Memcache reference The Memcache API and Using JCache.
Task Queue - Task Queue Reference The Task Queue API and Java Task Queue Configuration.
Backends - Backends Java API Overview and Java Backends Configuration.