I have relatively low end web servers outside a fire wall. They have 1GB RAM, a 1GHz Pentium III CPU, running RedHat 9.0 (soon ES). Behind the firewall will be much more robust AMD-64 server(s) with yet-to-be-determined OSes and 2-4GB of RAM. These server(s) will definitely be running the database management system, but I'm not sure how I should partition my application code.
From a performance standpoint, would I be better off with:
1) Apache 2.0 on the low end servers serving static content, using the JK2 connector back to JBoss on the faster server for JSP/Servlet/EJB processing
2) Tomcat 5 standalone on the low end servers for handling static content and JSP/Servlet processing, using remote calls (RMI) back to JBoss on the faster server for EJB processing
3) JBoss with Tomcat 5 on the low end servers for handling static content and JSP/Servlet processing, using using remote calls (RMI) back to a different instance of JBoss on the faster server for EJB processing
4) JBoss with Tomcat 5 on the low end servers for handling static content and JSP/Servlet/EJB, using a socket connection to the database on the faster server
I know the best performing architecture is to have the Servlet container in the same VM as the EJB container, so running JBoss with integrated Tomcat makes more sense than Tomcat Standalone and JBoss for EJB. However, I'm a bit less clear about the relative performance of using Apache with JK2 connector to JBoss vs. Tomcat with RMI to JBoss. Either way it seems, data will be moving across the wire.
Also, I'm just not sure if best overall performance wouldn't be having the web apps handled by the slower machines with the EJB and database handling being done by the faster machines.
From a security standpoint, I'm inclined to keep as little nonpublic code as possible outside the firewall. Thus, keeping the EJBs, and even the WAR files that just manage web app workflow, behind the firewall is safer, but may have lower performance than sharing the WAR file load with Tomcat 5 acting as web server and JSP/Servlet container.
Finally, from an ease of maintenance standpoint, it just seems easier to manage one flavor of server (JBoss) than it would be to manage instances of Apache, standalaone Tomcat 5, and JBoss, each with their own unique configuration requirements.
Whew! This is longer than I planned, but I've been wrestling with these choices for some time.
I welcome your ideas and suggestions.
I would recommend option 1.
Whilst I don't have figures to back this up, I would say that the overhead of communicating between Apache and the servlet engine on a different machine using JK2 is going to be much less that the overhead of communicating between machines using RMI.
Also I think it's better for security - JBoss opens a number of ports, some of which you don't want accessible externally. If you keep JBoss on the internal machine(s) you can restrict it's communication through the firewall to the JK2 port.
Also, (at least this is true with Jetty - I've not used the embedded Tomcat) there will be seperate HTTP and AJP13 (used by JK2) ports open on the servlet engine. By only configuring those webapps you want visible externally in the mod_jk2 settings you can have other webapps deployed on the server (e.g. the jmx-console) that are internally accessible on the HTTP port only.
Of course you need to do some testing once you've got everything set up - if your database is stressed then you may find having JBoss on the same machine isn't practical. If you have more than one back end server you could run JBoss on one and the database on the other. Again I think the overhead of JDBC communication between JBoss and the database on different machines is going to be less than any case where you have to use remote RMI. We have 2 servers running JBoss talking to a seperate database server.
Hope that helps.
Thank you for your thoughful response. I especially appreciated the insights into the security impact JBoss could have if outside the firewall.
It's also my plan to segregate the DBMS from the app server as you suggested.
I'd like to modify the premise of my question a bit.
If all of the web pages are JSP, does it make more sense to have Apache serving web content or would it make more sense to put Tomcat outside the firewall and RMI into JBoss/EJB?
The common view is Apache is better for serving static content (i.e. images and HTML pages), so it should be outside the firewall using mod_jk to get the JSPs and access Servlets. However, if the only static content Apache is serving are the graphics, does it still make sense to use Apache?
I'm not trying to talk myself into using Tomcat as my web server; I'm truly wondering how the trade-offs balance out between these two scenarios; i.e. Apache as web server vs Tomcat as web server when all the pages are JSP.
Thanks again in advance for your advice.
I do also think that solution 1 sounds as the best choice, though I do not have any figures to back it up, either.
But what if there is a cluster of JBoss nodes containing the business logic? Is it then wise to have embedded web servers running in the same VM as the JBoss server on each node?
The clustering documentation mentions having Apache mod_jk as a load balancer, using sticky sessions, in order to be able to have web applications participate in the cluster.
I guess that using a hardware load balancer improves performance compared to mod_jk, but is this setup, even with a fast load balancer, still better than having separate web server(s) talking RMI to the JBoss cluster?
I'm only considering JBoss 3.2.6 here. I haven't yet read much about the features in JBoss 4.
I may have some info that bears on this...
I have been performance testing the same app for 2 months with option #3 - Tomcat5/Apache in front, RMI to JBoss in back, JBoss to DB behind that.
Tomcat on Apple G5: 2CPU, 2G Ram, JBoss on Windows2000 4CPU,4G Ram, MySQL on Apple G5: 2CPU, 2G Ram.
Most web pages are JSP, and the ones that aren't are served by a Dispatcher servlet. All JBoss communication is thru stateful and stateless EJB facades, Entity beans are local only, BMP, CMT.
Current results indicate that RMI gets extremely slow as the load increases in Tomcat. Adding a user session every 2 seconds up to 500 concurrent requests causes EJBHome lookups alone to exceed 30s, and another 30s for create(). The AppServer and DB barely feel it at all. JBoss stats indicate that the create() never exceeds 250ms.
Tomcat is chewing ~90% of the cpu within 2 mins of the test (120 users), but I can't tell exactly where its happening, although 85% of processing time is spent accessing and executing EJBs. Memory is quite tolerable, and Garbage Collection never exceeds 4% of processing time (-XX:+UseParallelGC).
I don't know enough about jk2 Connectors to comment, but RMI isn't cutting it! To discuss directly, write me at firstname.lastname@example.org.
Hope this helps.