On Thu, Dec 15, 2011 at 12:25 PM, Christopher Schultz < ch...@christopherschultz.net> wrote:
> -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Hernan, > > On 12/14/11 7:15 PM, hernan wrote: > > On Wed, Dec 14, 2011 at 8:17 PM, Christopher Schultz < > >> What makes this "external" "program" non-multithreaded? Is it > >> actually not threadsafe? > >> > >> If you can't run it in the same process as Tomcat, then you'll > >> have to either use Runtime.exec or some type of wrapper around it > >> -- or have that process running completely separately (as a > >> daemon) and connect to it via sockets. Anything else requires > >> native code, which you definitely don't want. > > > > My external application is a java application that uses java > > wrapper (using JNI) for GLPK (written in ANSI C) > > (http://www.gnu.org/s/glpk/), and GLPK is not threadsafe. Yes, I > > will consider those alternatives, executing a new process when I > > receive the request (Runtime.exec) and a separated deamon receiving > > requests launching those processes. > > So, you're already running native code, eh? Well, you have several > options IMO: > > 1. Run the thing as a separate process, wrapped in Java. This requires > that you run Runtime.exec() and call the Java wrapper you have. > I'm not entirely sure why you'd bother with the Java wrapper if you > were going to call-out to a separate program, but it's an option. > See #2 for caveats. > As separate process, I thought a java "server" process with the wrapper that receive requests, launch a new process an response with the result. The servlet (thread) calls the process using some kind of client/server mechanism implemented in java (may be sockets). > 2. Run the thing as a separate process *directly*. That is, instead of > doing Runtime.exec("/path/to/java/wrapper"), you'd just do > Runtime.exec("/path/to/native/binary"). You'll get better performance > and will avoid the native code required to bridge from Java to > native, which is likely to improve stability. > On the other hand, Runtime.exec() is a monster, and you can deadlock > your thread(s) easily if you don't know what you are doing. > Runtime.exec() essentially requires 2 threads per call because you > have to monitor both stdout and stderr and consume them otherwise > you risk deadlock. You might want to use a wrapper library to improve > your chances. > I agree, just doing Runtime.exec(binary), the disadvantage with Runtime is that I'll not use java classes to comunicate input/output of the process. > 3. Run the thing in-process with Tomcat, but use some kind of service > that isolates and serializes access to the non-threadsafe library. > You can do this with a singleton (or something like it) that has > a synchronized "run-GLPK" method: that will restrict callers such > that only one of them can use the library at a time. > I highly recommend that you try to acquire a lock using a timeout > instead of just blindly calling a synchronized method otherwise > you might end up in a deadlock situation if the library (or your > code) stalls at some point. > I've run successfully using syncronized methods, but I have to handle concurrent requests and I don't want to serialize them because the response times may be very different between them and I don't want some user have to wait a lot for a "simple" request. > Another caveat: running JNI within a server process has inherent > risks of crashing the native module (if there is a bug in DLPK or > in the native wrapper around it) which will bring-down your whole > Tomcat service: that's obviously bad. > This is the main concern for me. For that reason I prefeer run glpk in a different os process. I see two big ways: serving each servlet request with a different process or run a different process/es dedicated only to glpk. The first way is what I have to learn, but it seems that tomcat does not support. In the second, I have more job coordinating processes and manipulating input/output. > 4. As I suggested before, run GLPK as a daemon process and communicate > with it via sockets or whatever. Has anyone written a GLPK-service? > > So, perhaps the simplest thing to do is #3, but it has the most > runtime risks. The safest thing is to run as a separate process and > communicate via sockets, but that might require significant investment > in infrastructure (to build the service, then call-out to it). > > Are there any other requirements? For example: do you need to be able > to handle multiple simultaneous incoming HTTP requests that all need > to use GLPK? Or, is this relatively rare? If you need high > concurrency, then option #3 simply isn't going to work unless the > operations are very fast (which I suspect they are not). > > Do you have any idea how stable GLPK is? How about the native wrapper > in Java? In my experience GLPK is stable, and I've been doing some (serialized) tests on java wrapper and they run successfully. But I'm not 99% sure that will be perfect, and mainly I don't trust in the program/programmer (me) that uses the library. I don't want that tomcat crash due to some request. > > Can I configure tomcat for running a new (or different) process for > > each request? > > No. Tomcat runs in a single JVM, pretty much by definition. You can > get Tomcat to run a *servlet* as a new instance of the class that > defines it (by using SingleThreadModel) but that does not help you, > here, and is a deprecated capability anyway. Ok > > or I have to run Apache HTTP Server and connect it to Tomcat? > > That's not necessary, either, although it might make it easier to wrap > a service around GLPK with a simple set of CGI-BIN-style scripts > written in Bash, Perl, etc. Ok > > If I have to run Apache HTTP Server which mechanism do I have to > > connect it with tomcat? using Jk connector is the standard way? > > If you have to add httpd to the mix, you basically have 3 choices: > > 1. mod_proxy_http (uses HTTP protocol, comes bundled with httpd) > 2. mod_proxy_ajp (uses AJP protocol, comes bundled with httpd) > 3. mod_jk (uses AJP, you must build this separately) > > Although mod_jk does not ship with httpd, it has more flexible > features and tends to be more up-to-date because it has releases that > aren't tied to httpd's schedule. > > > Do you recommend me to read > > http://tomcat.apache.org/connectors-doc/reference/apache.html ? > > I've found also > > http://tomcat.apache.org/connectors-doc/reference/apache.html but > > it seems to be outdated. > > Those are the same URLs and I believe it is up-to-date. I would only > read this if you have chosen to use httpd with mod_jk: that's what the > documentation is for. If you want to use mod_proxy_*, you should read > the documentation for httpd here: > http://httpd.apache.org/docs/2.2/mod/mod_proxy_http.html > or > http://httpd.apache.org/docs/2.2/mod/mod_proxy_ajp.html > > I really think you need to decide (or tell us) what your requirements > are before you start charging-into a decision like adding a completely > new component to your environment. > > Connecting apache htttpd server with tomcat, can I run several tomcat instances and run each http request in a different tomcat instance? I know that this is not the tomcat philosophy, but I just want to know if it is possible or is common this approach for this kind of situations. My principal requirements are: stability (main concern), scalability, serving concurrent requests (no more than 100 concurrent requests). If possible: flexibility/maintainability. I think that your option #4 is the appropriate in this situation. Thanks a lot for your comments and suggestions!! Regards, HernĂ¡n