Hot on the heels of Google Widget Toolkit(GWT) switching to Jetty, the little server that can has received some more Google luv’n!   Google’s new App Engine Java service is powered by Jetty! With App Engine, you can build web applications using standard Java
technologies and run them on Google’s scalable infrastructure.
Initially it is a little difficult to see Jetty in use, but you can see the jetty classes in the SDK download and if your application throws an exception then investigation of the stack trace in the log reveals the Jetty servlet container is used.
Not only that, the stack trace and other documentation show that Google have really exploited the embeddablility and extensibility of Jetty at a number of levels:

  • They are using their own RPC style connector to receive requests from their front end web servers.
  • They use the google account authentication as the only supported authentication mechanism.
  • The HTTP sessions are clustered via the database or memcache
  • There is an appengine-web.xml configuration file
  • Jetty is embedded in their SDK and eclipse development plugin.

Thus Google have plugged in many new and/or extended components in a way that validates our open, component based architecture.   When it comes to application servers we do not believe that one size fits all and strongly encourage such customization for purpose.
We are really pleased that the google App team picked Jetty for their hosting service and welcome them to the ever growing list of Jetty powered projects!
 
The revealing exception:

javax.servlet.ServletException: This is an exception	at com.acme.HelloWorld.doGet(HelloWorld.java:48)	at javax.servlet.http.HttpServlet.service(HttpServlet.java:689)	at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)	at org.mortbay.jetty.servlet.ServletHolder$SingleThreadedWrapper.service(ServletHolder.java:617)	at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1093)	at com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:35)	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)	at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1084)	at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:360)	at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)	at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)	at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:712)	at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405)	at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:237)	at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)	at org.mortbay.jetty.Server.handle(Server.java:313)	at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:506)	at org.mortbay.jetty.HttpConnection$RequestHandler.headerComplete(HttpConnection.java:830)	at com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:63)	at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:381)	at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:125)	at com.google.apphosting.runtime.JavaRuntime.handleRequest(JavaRuntime.java:235)	at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:4547)	at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:4545)	at com.google.net.rpc.impl.BlockingApplicationHandler.handleRequest(BlockingApplicationHandler.java:24)	at com.google.net.rpc.impl.RpcUtil.runRpcInApplication(RpcUtil.java:359)	at com.google.net.rpc.impl.Server$2.run(Server.java:792)	at com.google.tracing.LocalTraceSpanRunnable.run(LocalTraceSpanRunnable.java:56)	at com.google.tracing.LocalTraceSpanBuilder.internalContinueSpan(LocalTraceSpanBuilder.java:489)	at com.google.net.rpc.impl.Server.startRpc(Server.java:748)	at com.google.net.rpc.impl.Server.processRequest(Server.java:340)	at com.google.net.rpc.impl.ServerConnection.messageReceived(ServerConnection.java:422)	at com.google.net.rpc.impl.RpcConnection.parseMessages(RpcConnection.java:319)	at com.google.net.rpc.impl.RpcConnection.dataReceived(RpcConnection.java:290)	at com.google.net.async.Connection.handleReadEvent(Connection.java:419)	at com.google.net.async.EventDispatcher.processNetworkEvents(EventDispatcher.java:733)	at com.google.net.async.EventDispatcher.internalLoop(EventDispatcher.java:207)	at com.google.net.async.EventDispatcher.loop(EventDispatcher.java:101)	at com.google.net.rpc.RpcService.runUntilServerShutdown(RpcService.java:249)	at com.google.apphosting.runtime.JavaRuntime$RpcRunnable.run(JavaRuntime.java:373)	at java.lang.Thread.run(Unknown Source)



Edited 11 Apr 2009:
In response to the questions about continuations, we found this discussion on the google app engine forums, which says:

“We do not support continuations.  All requests need to complete their work within the ~30 second deadline and then return control back to App Engine. There is not currently any support for chunked transfer encodings, hanging gets, or background processing, so continuations would not be very useful.”

This is interesting, but we’d like to feedback to google that there are plenty of interesting uses for continuations that do not need waits longer than 30 seconds, background processing or chunked responses:

  • We encourage the use of long polling techniques that always send complete responses and thus don’t need chunking etc. 
  • In many cases, background processing is not needed. Suspended requests can be resumed by other requests (eg chat, auctions, collaborative editing etc.) or even other responses completing (eg quality of service filter).
  • For interactive web applications, having a long poll of 20s will still give great latency and throughput advantages over a more frequent polling solution.

Now it maybe that Googles RPC connector cannot operate asynchronously, so they are forced to have a thread allocated.  If that is the case, then they should talk to us and we’d be please to teach them how to better scale their infrastructure (we also specialize in teaching egg sucking 🙂
 
 



7 Comments

MarkB · 10/04/2009 at 09:03

That’s great news Greg. I was wondering. Any idea whether it supports continuations?

Karl Matthias · 10/04/2009 at 22:18

Hey Greg, congrats on Google using Jetty so heavily! Clearly they recognize good technology.
On a side note, it seems the webtide blogs are not working with Planet Eclipse. Your RSS feed encodes the HTML tags rather than encapsulating them in CDATA tags, and the Planet scraper doesn’t seem to deal with them well.
Cheers,
Karl

Greg Wilkins · 10/04/2009 at 23:26

MarkB,
there is a chance that continuations will work as they have extended our core connection classes, but a lot depends on how they have implemented some key methods. We’ll give it a go in the next few days and see.

Greg Wilkins · 10/04/2009 at 23:56

I’ve edited the blog with some more information regarding continuations

Alessandro Alinone · 05/05/2009 at 22:09

Greg, that’s really cool! Congrats.

SingTel Accelerate · 08/09/2010 at 23:59

[Trackback] 30 days to SaaS by Intalio

SuperEngine · 28/07/2011 at 03:47

Great ,more and more business will adopt jetty as their power application server.
I want to build a PAAS platform base on jetty,does any one can give me any suggestion
on architecture ? Trade King

Comments are closed.