How to integrate an external process which is invoked repeatedly into a Java webapp?
I am trying to integrate a non-Java executable into a Java webapp on the server-side (Linux).
Some details about the executable:
Written in C++. The executable takes some input either from stdin or file and generates an output file. The executable is not designed to be a long running process i.e it generates an output and then dies out.While starting an individual process for the executable is fairly inexpensive, the number of calls made to it can be high. This can result in spawning too many processes which could degrade server performance.
How can I write some wrapper or utility (in Java) around this exe, that I can run efficiently as either
- a thread from within my Java app
- a long-running external process
PS: I know that I can start an external process using Runtime or ProcessBuilder in Java and could probably make 开发者_运维知识库it multi-threaded and use some queueing too, but that does not solve the issue of starting the process over and over again.
if you:
a) Can modify the source code.
I would recommend you yo create a long running process and expose it as a webservice. This way the process will only be sitting there waiting to be invoked.
b) Have the source code/headers but you can't modify it.
Probably a good idea would be to integrate it as library and invoke it from java, either with JNI or JNA, although this may be painfully hard.
C) Don't have the source code or can't modify it.
Then there are not much options, you have to create a thread queue and from there throttle the process creation.
If starting up the C++ application takes too long, it is almost a certainty that you are going to have to write some C++ code to avoid this.
One alternative is to refactor the C++ into a library with a suitable API, and use JNI or JNA to call the API from Java. However, JNI / JNA are difficult to use and have the tendency to destabilize the JVM. When something goes wrong (e.g. your JVM crashes), debugging is difficult.
A better alternative is to refactor the C++ application to run as a daemon process. Replace the 'main' entry point with code that sits in a loop doing the following:
while (true) {
read request from a socket / pipe
process request
write answer to socket / pipe
}
If you use a pipe, you can have your Java webapp launch the C++ application using Runtime.exec(...)
and then read and write messages via the pipe streams. If you use an (IPC or network) socket, you could do the same or make the C++ application multi-threaded so that it can handle more than one request at a time.
One issue that you will need to consider is multi-threading. You web container (the thing that runs your webapp) is likely to be multi-threaded by default, so you will need to implement the Java side to cope with the multi- or single-threaded nature of the C++ side. This might be as simple as making the Java-side object that is used to make requests a singleton with synchronized methods. However, that could be a performance bottleneck.
Throtteling in Java can be done using a suitable Executor. There are plenty easily available in Executors - I think the fixed size thread pool is exactly what you need.
http://java.sun.com/javase/6/docs/api/java/util/concurrent/Executors.html#newFixedThreadPool%28int%29
How many processes is "too many"? I suggest measuring the performance before going further. It may be the case that you can start and run many more processes without problem than you expect, especially since the code of the program will be shared in memory across all instances.
精彩评论