I normally like to deploy my JBoss server apps with 2 or 3 “tiers” of components:
- A
my-ws.warfile consisting of all my server’s web services, comprising the “web tier” and deployed to JBoss’ web container; and - A
my-esb.warfile consisting of my server’s “ESB” (service bus), basically an ESB built with Apache Camel and used for servicing asynchronous requests - 1+
EJBs consisting of all my server’s business logic, comprising the “business tier” and deployed to JBoss’ app container; all EJBs are responsible for servicing synchronous requests
So the Web Services (my-ws.war) are the “gateway” to the backend, and based on the nature of the request, the Web Services know to route them on to the appropriate EJB (in the case of a synchronous request that needs to be responded to in a timely manner), or it routes them on to a queue where they get picked up and processed by my Camel-based ESB (in the case of an asynchronous request). This has always worked for me and I really like the architecture.
I am now designing my first GAE backend and am struggling with trying to figure out how to map this same architecture onto a GAE platform.
Obviously, I have to deploy everything as a single WAR file (no more EARs or EJBs). But what I’m just not “getting” here are:
- If a Web Service determines the request is asynchronous and should go on the ESB, I can enqueue the request to a task queue, but not sure how I instruct the first endpoint of my Camel route to pick up the task and begin processing it (I’m used to working between Camel and ActiveMQ)
- I assume my ESB should be deployed to backend instances so its not limited by time or threading constraints, yes?
- If a Web Service determines the request is synchronous and must be quickly responded to, I need the GAE version of an EJB. Do I just make handler POJOS and route the requests to them? My Web Services will be as multi-threaded as possible (I believe 10 threads is the max for a frontend instance) so I assume such handler POJOs would need to be thread safe, yes? Or is there a better way to simulate EJBs/modularized-business-logic on GAE?
Also, if anyone sees anything inherently wrong with trying to map my normal architecture to GAE, please speak up and let me know what/why! Thanks in advance!
The architecture you describe is straightforward. Whether the implicit complexity is warranted for your application is something you can decide.
I am not familiar with the specifics of Camel, so you’ll need to try and map the concepts here on top of it. But, this should really be no big deal. At this level and ESB is an ESB is an ESB.
For #1, there’s two options. GAE has
pushandpullqueues.Pushqueues are set up by you and managed by GAE and can only be used within the GAE environment.Pullqueues are set up and managed by you, but can drive both GAE and external applications.A
pushqueue, to your application, is nothing more than a normal web request, the detail is that GAE is the client making the actual request. You post to the a queue the URL that it’s going to and its payload, GAE captures, routes, and throttles the requests to your URLs. In order to inject a request on to Camel, if you can pump a Camel pipeline from a Servlet or any arbitrary Java class, then you can do that here. I know Camel has a bunch of connectors and listeners and such, but in this case you just need a simple, code based injection point. I have no doubt that Camel can do this, I just can’t say the details.A
pullqueue is quite different. Here, you will need to have a free running thread(s) that pull tasks off of the queue (using the GAE lease mechanism) and process them. You may well be able to leverage some Camel infrastructure to create apullqueue compliant thread end point and let Camel manage that whole kit. But in the end, you have to spool up the threads, manage how many you want to run, monitor them, shut them down, etc. So, there’s a bit more work to actually do here in contrast topushqueues.Pushqueues are easier from an internal infrastructure point of view if having everything within GAE is a reasonable requirement. Thepullqueue can be pulled from an external source via an HTTP request if you need some external integration.So, while Camel may not have out of the box capability to manage a GAE
pullqueue, I’m betting it’s pretty straightforward to adapt an existing component to handle this, then you can let Camel manage the entire thing. If you’re already comfortable with Camel at this level, this may well be easier to work with for you.For #2, the two primary benefits of a GAE backend are stability and longevity. The normal instances are there as generic web apps, suitable for load balancing. GAE creates and destroys these instance based on traffic and response patterns dynamically. But it’s quite possible to have zero instances of your app actually running at any particular time, with GAE spinning them up when it sees the first requests. So, any internal (i.e. not persisted in the DB) managed state has no guarantee of having any real lifespan.
The backends are instances under your control. They’re much like an instance at other cloud providers. You start it up, you size it, you route traffic to them, you shut them down. For that you get better assertions of uptime and system capacity.
If your requests are not particularly demanding in terms of CPU time or resources, you may well not need a backend instance, especially for
pushqueues. Basically imagine getting a request from a web browser, and handing off information to the GAE task system. All GAE is going to do is immediately call back just like any other request. To your app it’s going to look just like normal web traffic, it doesn’t “know” it’s from GAE.So if you put a 1000 requests all at once on to the queue, GAE will spin up as many instances of your app as necessary to meet the bucket rate and message rate. When those 1000 requests are done, GAE will shut down any quiet instances. Just like if you suddenly got a 1000 visitors to you application who then suddenly leave.
For
pullqueues, you pretty much need to have a long running instance, since they’re really the only kind the can handle long running threads that sit on the queue waiting for traffic. But that means that you’re running all the time, traffic or no.For #3, this is mostly straight forward.
In their most basic form, an EJB (by which I assume you mostly mean Stateless Session Beans) are basically a POJO with a defined life cycle wrapped in a transaction context. You can replicate SSBs fairly easily as you can write your own “mini” container:
At 10,000 feet, that’s the gist of it. Fortunately you don’t actually have to write this yourself. Both Spring and Guice can handle much of this for you, notably injection of resources and other beans. If you don’t use the EJB lifecycle, interceptor or transaction mechanisms heavily (or at all), that simplifies things as well.
In the end, assuming you don’t have static values in your SSBs, you do not have to worry about thread safety so much because you simply create a new instance for each request. Simplifies the problem immensely in contrast to Servlets.
You can also look at a decent Action Framework like Stripes or Struts 2 which offers a lot of these life cycle patterns etc. around your web requests. Can simplify things.
So that handles the big 3. All that said, I am not a “battle-worn” GAE veteran, my GAE app was quite small, and has not used any of these technologies. It’s all “book learnin'”.