One my customers has very strict requirements about how they can deploy a web application. They require it to be deploy-able as WAR within a Java server like Tomcat. Our application however is written in golang and compiles into an executable server.
The only solution I could think off would be to start a long lived golang process in the background which listens on a non-standard port like 8080 and then put some kind of a proxy in java which would transparently proxy all HTTP requests and responses to this process.
How should I go about implementing this ? I'm not at all familiar with Java Servlets and running long running processes like this in the background.
My main concern is if something like this is standard,
would it affect the JVM's memory usage, etc ?
Would the server allow my golang process to allocate the required
amount of memory ?
Would the JVM be able to track it's processor utilization ?
Is there a better way to do this maybe ? Like some kind of inter-process communication mechanism ?
If HTTP is the only API your Go application exposes, then you're only left with the option to just send a HTTP request to Go. Yes you can start the Go executable as a child process from the JVM using a ProcessBuilder. But that's not truly embedding go within your WAR. You can use JNI (Go bindings are called GoJVM) to invoke native routines in Go from Java, but then you have to make a lot of adjustments to your Go code base as well.
What you are looking probably for is indeed a reverse proxy. It's not frequently done in servlets / application servers, because this is usually done in load balancers already. So usually that would be NGINX or httpd with mod_rewrite. For application servers, you can use a proxy servlet.
Examples:
https://github.com/mitre/HTTP-Proxy-Servlet
https://sourceforge.net/projects/j2ep/
The memory footprint is usually not to bad, because you're essentially only connecting the streams. The JVM will be able to track processor and memory utilisation - if implemented properly and the Go executable runs on the same server. Obviously the Java specific statistics don't make much sense anymore, as you're only using your Java server as a pass-through.
Sounds like you will be in trouble though. If my strict requirement was a WAR-archive that can be deployed to an application server, I wouldn't accept another executable added to my stack. Reverse proxied or not.
If they want war, give them war!
Write a thin layer web service that has the executable embedded as a resource that executes it to bring up the go server and accepts web calls and does a pass through to the go service.
Achieves nothing I hear you say? Well, neither does their arbitrary requirement that was probably put in place by someone who's long since left the company, and/or because they lack the confidence/experience/ knowledge to operationally deal with other forms of deployment. There is no particularly good reason to deny your service to be deployed except the work required to establish proper operational procedures (laziness).
Just follow the letter of their rules, not the spirit, and be honest if asked about your implementation. They won't mind.
This may sound like a rant, but IMHO and experience, this kind of approach is reality and the drivers for the requirement are emotionally based, so a somewhat emotional answer is warranted.
Related
In our system we have a legacy standalone java application which we are trying to made available for new webapps we are developing all together running in a server (f.e. Tomcat)
In order to made requests to this app lighter we thought about made them directly to the same vm using jndi instead of developing a webservice interface.
I would like to start this application environment in some webapp context and make some API available to other webapps and invoke interfaces' methods.
I've not been able to bind this objects by JNDI in the Tomcat's read-only Context without adding the app in the Common lib, when I get more problems due to incompatibilities between dependencies versions. Maybe the best solution is to deploy these interfaces as EJBs so I'd use a Java EE Server instead of a servlet container. Or maybe I'd use some other framework such as Camel or something.
Thanks in advance and any suggestion will be helpful.
I would suggest to wrap your legacy java interfaces in REST. When you expose them as REST APIs, they will become available for any client, not only java. Also you don't need any Application Servers for that, all you need is a jar file for your REST reference implementation.
From performance perspective, well, I know theoretically JNDI should be faster, but in the real world the difference in performance becomes significant ONLY for very very performance intensive applications.
However, if performance is your primary requirement then wrap your legacy interfaces in EJBs.
Manual JNDI/RMI lookups are going to be the fastest, BUT and this is a rather big but, unless you are well experienced in network programming and multi threading, I would advise you to steer clear of that, and use a container. There are a lot of nitty gritty details that the container takes care of and you can concentrate on implementing your business logic.
I've been researching Apache's commons-daemon and it seems pretty cool: basically its an API as well as a library that helps register your JAR with the underlying OS so that it can be started and stopped like a daemon service. Additionally, it intercepts OS signals that would normally kill your app and instead gives you a chance to shutdown politely.
So it's got me wondering, if given the choice between deploying your business logic inside EJBs and wrapping them in a container like OGS or JBoss, why not just create a daemon JAR that listens on a port and responds to client requests?
Is it just the benefit of all the features/services that an app container provides out of the box (security, logging, etc.), or are there times when it would be favorable to choose a daemon over an app container/EJB solution?
Basically, what I'm asking if: when is it more appropriate to use an app container/EJB solution, and when is it more appropriate to use commons-daemon to help build a system-level service (in Java)?
Disclaimer: just interested in these two choices, I am aware that other solutions exist (web containers, ESBs, OSGi, etc.). But for the purposes of this question I am only interested in hearing the reasoning between app container or daemon solutions. Thanks in advance!
Why don't you look at it like System level (daemon) vs Application level (in container)?
This will give more or less clear distinction (especially if worked with Linux some time).
For Daemon:
has its own life cycle (you can start and stop it separately);
different privileges (could be run under different user);
use case is something like CRON, MailServer, synchronization and any system-level service.
For Container:
managed app (by some privileged user via Container console);
plenty of out-of-the-box features (which you'd already mentioned);
use case some general case business application.
Well the simple answer is yes, the app server (Glassfish or JBoss) give you plenty of nice things that you would have to implement or setup yourself in a plain Java SE app.
However it is not so black and white, and you can get a lot of the application server goodness with very little effort, I am in the process of writing a blog series on exactly this topic.
My reason for not using an app server, was that we had a project for a widely distributed software product, and we wanted to avoid having to patch and maintain thousands of application server instances!
However if your app will be running in one place, there is little reason to go Java SE.
I'm a long-time client-side (Swing) developer and I operated pretty much by myself in the same job for a long time. Working from home in a vacuum, I was pretty much completely isolated from the community. I recently took a position as a server-side Java guy for a startup, and I'm learning a ton of stuff but I'm the only Java person and am pretty much on my own again. Having never done server-side Java before, so much of this stuff is completely new and I feel like I have no idea what the normal best-practices are, or I don't have an intuitive feel for what tools to use for what jobs. I keep reading and reading various Internet sources (SO is awesome!) trying to bulk up my knowledge, but some things seem hard to search for because they don't have any obvious keywords. Hopefully some of you gurus here can point me in the right direction.
I'm in charge of implementing our backend REST service, which for now supports our website and an iPhone app. We're doing a social media site, eventually with many different clients. Currently the only clients of the service are our own website and our own iPhone app. I'm using Jersey, Spring, Tomcat, and RDS (Amazon's MySQL) on Amazon's EC2 platform. Our media storage is via S3. I've picked up all of these things pretty quickly and so far so good -- things are working fine with the website and the iPhone app. Cool.
Our next step is adding some long-running server-side processing. This processing is basically CPU-intensive stuff that doesn't involve any communication until it's done. I'm trying to figure out what the best way to handle this is. I'm thinking of using Amazon's SQS to queue up jobs in response to the REST events that should trigger them, but I can't figure out how I should handle the dequeuing and processing. I know I need some threads somewhere that take jobs off the SQS queue and process them, and then tell the REST service that the job is done. But where do these threads live?
In a plain "java -jar jobconsumer.jar" process on another EC2 instance that starts a small thread pool. Maybe use Spring to wire up this piece and start it running?
In a webapp deployed in a container like Tomcat on another EC2 instance? I don't really know what benefits I would get from this, but somehow running in a container like this seems more stable? Does this sort of container even really support long-running processing loops, or is it just good at responding to HTTP events?
Now that I write it out like that, I don't really see why I would want to use a container. It just seems like an over-complication. However, the Java community seems so centered on these types of containerized, "managed" environments that to not use a container seems somehow wrong. I feel like maybe I'm not understanding what some of the major benefits of these containers are? I mean, beyond the obvious benefits of the web-facing Servlet and JSP specs. Would any of the functionality of those specs help me out with something like this?
For a regular Java web app, you almost certainly want to be using one of the Servlet containers such as Tomcat - it takes care of accepting connections, parsing and serialising HTTP messages, JSPs, SSL, authentication, etc for you.
For a non-web app, the argument for using Tomcat (or similar) is weaker, but there are a few reasons to still consider it:
straightforward to add JSPs for querying and managing the app or add a web API in future
easy distribution of releases (one .war vs. an unholy mess of jars and config files)
hot deployment (although I've yet to see anyone using this for anything serious)
In terms of long-running processing loops, Servlet containers don't help you out beyond notifying your ServletContextListener when the app starts, so you can kick off any long-running tasks.
It's worth noting that if you're already using Spring, it's relatively easy to switch from a stand-alone app to a container using ContextLoaderListener, so it shouldn't be a problem if you decide later that you need the web stuff.
We recently faced a similar question, as we are hosting a large distributed service on EC2.
In short, we are very happy with Jetty 7 as a container. We use it for our user-facing-www, public-api, and internal-backend-api services. In some cases we use it for non-api services such as a workqueue, simply to expose a bit of status & health info for our monitoring.
The great thing about Jetty (any version) is that it can be configured in ~5 lines of code, with zero external config files etc. It's not a container specifically, but an http server that you can embed.
We use Guice for dependency injection, which also favors config-file-less implementations.
Long lived Java processes are nothing to worry about - you basically bring up your servers / threads / threadpools in your main method and don't call System.exit until you want to shutdown explicitly.
is it possible to install more than one java application server on one server or VPS ?
i want to install JBOSS , TOMCAT , WEBLOGIC and my be more.
how this is possible and what the benefits and disadvantages ?!
It is possible, if you want to try all of them. You just have to select different port for each services.
Is there a real use-case ? You could have an application bound to your application server, and you could want to run different applications.
Yes. The usual problem is that a given port can only be used by a single process.
Hence you cannot have both JBoss and Weblogic on port 8080. Also a lot of extra ports are needed for normal operation. This is at best tedious.
This is possible. You need to take care about port's these servers use.
Also you need to check what resources (cpu's/core/RAM) you have on your server. Your system should have ample resources to Run multiple servers.
I don't know whats use case, But if possible I would prefer having various webapps on single Java applicationserver.
As already mentioned above it is possible but it is a configuration management nightmare.
If it is for compatibility testing, I would look at EC2 or similar timebased hosting and , put an 1 app server in 1 image and spin up each image in turn and shut it down after the test is finished.
The money that costs is paid 10x by not having to edit all kind of configuration files and debugging weird conflicts.
Yes, it is possible.
Pros:
You don't need extra servers to run your appservers, so you save in physical/virtualmachines. This helps a lot when you're prototyping something, and also in functional testing, because you can share servers between applications.
Some applications may need incompatible appserver settings, so you must run them in different appservers, side by side.
Downtime of one appserver doesn't affect other appservers.
Cons:
You must make sure that every appserver gets enough share of CPU, memory, etc.
You must assign port numbers to each appserver
You are making each environment's performance dependent on each other's.
So, it is something that you do mainly to experiment/develop/test. In production environments you have to be much more careful when running appservers side by side..
I'll need to develop a Java service that is simple because:
It only communicates via a TCP socket, no HTTP.
It runs on a dedicated server (there are no other services except the basic SSH and such)
Should I make this a standalone service (maybe in something like Java Service Wrapper) or make it run in a container like Tomcat? What are the benefits and detriments of both?
If you aren't working with HTTP, you will have to build your own connectors for Tomcat. When I've written these types of applications, I've just written them as standard Java applications. On Windows machines, I use a service wrapper that allows them to be part of the Windows startup process. On non-windows machines, you just need to add a start up script.
Using a container (regardless which) buys you that all the details about starting, stopping, scaling, logging etc, which you have to do yourself otherwise, and it is always harder than you think (at least when you reach production).
Especially the scalability is something you need to consider already now. Later it will be much harder to change your mind.
So, if somebody already wrote most of what you need, then use that.
Tomcat doesn't sound like a good choice for me in your situation. AFAIK it's primarily made for Servlets and JSPs, and you have neither. You also don't need to deploy multiple applications on your app. server etc. (so no benefit from ".war").
If you need dependency injection, connection pooling, logging, network programming framework etc., there are a lot of good solutions out there and they don't need tomcat.
For example, in my case I went for a standalone app. that used Spring, Hibernate, Netty, Apache Commons DBCP, Log4j etc. These can be easily setup, and this way you have a lot more freedom.
Should you need a HTTP server, maybe embedding Jetty is another option. With this option too, you have more control over the app. and this can potentially simplify your implementation compared to using a tomcat container.
Tomcat doesn't really buy you much if you don't use HTTP.
However, I was forced to move a non-HTTP server to Tomcat for following reasons,
We need some simple web pages to display the status/stats of the server so I need a web server. Java 6 comes with a simple HTTP server but Tomcat is more robust.
Our operation tools are geared to run Tomcat only and standalone app just falls off radar in their monitoring system.
We use DBCP for database pooling and everyone seems more comfortable to use it under Tomcat.
The memory foot-print of Tomcat (a few MBs) is not an issue for us so we haven't seen any performance change since moved to Tomcat.
A container can save you from reinventing the wheel in terms of startup, monitoring, logging, configuration, deployment, etc. Also it makes your service more understandable to non-developers.
I wouldn't necessarily go for tomcat, check out glassfish and germonimo as they are more modular, and you can have just the bits the need, and exclude the http server.
We faced a similar decision a while back, and some parts of the system ended up being jsw based, and the others as .war files. The .war option is simpler (well more standard for sure) to build and configure.