Showing posts with label Tomcat. Show all posts
Showing posts with label Tomcat. Show all posts

Thursday, June 04, 2009

More on FutureTask

Adding to my previous FutureTask post: Future is a very nice interface, but the main problems with FutureTask are the lack of a callback and the clumsy constructor that requires a Callable. I guess their main use case was someone creating a FutureTask that performs a slow operation - as in my example, it is relatively easy to wrap the method in a Callable and then execute the FutureTask in a thread pool.

It is possible to add a callback by overriding FutureTask.done(), which is called after FutureTask.set().

There are few tricks to better use FutureTask. Let's say you have an operation that happens in background already, and you're notified with a callback. You want to wrap it in a Future to make it easier to use:




interface Callback {
void done(Object1);
}

void doSomethingAsync(Callback callWhenDone) {
}

class MyFuture extends FutureTask {
public MyFuture() {
// FutureTask _requires_ a callable - even if it's not using it. Let's give him a dummy one.
super(new Callable() { public Object1 call() { return null; }});
}
// set() is protected - need a visible method to let future know the result
public void gotTheResult(Object1 result) {
this.set(result);
}
}

Future<div class="youtube-video"><object1> getSomethingFuture() {
final MyFuture res = new MyFuture();
// We _don't_ submit it to an executor - so run() will not be called
doSomethingAsync(new Calback() {void done(Object1 result) {
// do what innerRun() does - i.e. call innerSet with the result.
// innerSet() will set state to RAN , even if the callable was never called.
res.gotTheResult(result);});
return res;
}



Friday, March 07, 2003

HelloWorld - finally !

Last night I got the first "hello world" page from tomcat5/JMX. No server.xml, no fat, only a small set of mbeans driven by ant. Things were very close for a while but never quite work completely. There is still a lot of work, mostly downhill IMO.

I can't wait to finish - I'm in overload mode for some time, doing too many things at once.

Saturday, March 01, 2003

JMX clustering

I don't like session clustering for a lot of reasons. Clustering in general is great - but the servlet session API just doesn't have enough power to allow a correct and efficient use of clustering. The use case for caching some values is compromised,

there is no transaction support, no feedback or control - users are much better served by assuming the session is transient, and using database or user-controled clustering.



By clustering I understand broadcasting and mirroring some data on multiple instances - there are many other meanings. It is a very powerful tool if used right.



There is one use of clustering that would be extremely intersting - broadcasting and clustering the JMX attributes. The idea is to have a global view - each tomcat instance could brodacast its mbeans and attributes, and may be able to take more inteligent decisions knowing the state of the other instances. And the admin console would get info from all instances.

Tuesday, February 25, 2003

JMX console

One of the main benfits of JMX is the ability to "see" what happens at runtime and to tune the process. The admin interface is good, as it provides a nice interface - but for advanced use you need a low level console. Each JMX tool has its own console - and that may be a bit confusing if you switch them often.



An interesting fact is that most of the consoles can be used with other JMX implementations - with almost no effort. That's a pretty good proof of the benefits of low coupling.



The JBoss console is a webapp - you'll need to copy jboss-client.jar and log4j.jar in WEB-INF/lib, since it's not self-contained ( there are few utils for logging ), but besides that you should be able to use it with any servlet container that has JMX support. It may be worth precompiling the jsps.



MX4J doesn't depend on a servlet container - it uses an interesting ( but slower ) XSL and its own HTTP listener. All you need to do is load the mbeans. Commons-moder provides a one-line mechanism - I'll comment on it later ( I'll do few more enhancements and simplifications ).



JMX-RI has the fastest console - also contain its own HTTP listener and is packed as few mbeans. I have no idea what's inside - so I usually preffer one of the other two.



Another note - in tomcat ( any - if it uses jk2 and coyote ) you can just add a "mx.port=PORT" in jk2.properties and MX4J or JMX-RI console will be started. You need to copy one of the 2 in server/lib ( mx4j-tools.jar or jmxri-tools.jar ). If mx4j is used, it'll also try to enable the RMI connector. Most of the code will fail gracefully, without affecting the rest. The startup time overhead is quite small.

Sunday, February 02, 2003

JMX servlets

JSR77 and tomcat supports JMX for servlets ( and many other components ). This works by exposing the wrapper - and providing all kind of information. Extending this to the real servlet ( the code written by the user ) would move the servlet in the current century, and is quite easy to do.



Servlets are configured using the ServletConfig passed at init time. We could write a simple module ( mbean ) that listen for JSR77 mbean registrations. When j2eeType=Servlet is registered, it can look for the "real" servlet and check if it is an mbean ( implements the *MBean interface, etc). If so - it will just configure the servlet using JMX patterns ( including init()/start() lifecycle pattern ).



The JMX console would show what happens inside the servlet - and allow runtime tunning and reconfiguration of the servlet. Whenever we support the JMX persistence - we can extend this to the servlet and context init params.



Another extension would be to support ant-like patterns - a serlvet ( that implements single thread model ) can automatically get the request parameters transformed into setter calls, like an ant task, and then an execute() method to perform the request. This can be supported with a base class - and would allow a number of optimizations and more important - will greatly increase the readability of the servlet code.

Monday, January 27, 2003

Java security

Interesting article on security, thanks Jon for posting it.



It shows ( again ) that java without sandbox is not safe - private fields, classloaders or any other tricks are just dangerous illussions of security. The security is inside the (sand)box.

Friday, January 24, 2003

TLD listeners and context initialization

Updated and reformated:



JSP spec allows TLDs in any .jar file and in WEB-INF. TLD may contain application listeners. That means tomcat must scan all the .jars, as well as all .TLDs. Even if the app has no JSP or taglib - we still must can all .jars.



This is a pretty expensive operation ( some small test show 2/3 of the startup time on some apps with a lot of jars going in .tld processing ). If you have a lot of .jars or tags - it will be visible.



The simple solution that I checked in will just cache the result in a .ser file in work, and avoid re-scaning if no .jar or .tld has changed. It's "ant-like" ( setters and exec) so it could be used in the deploy tool ( if we had one :-).



Someone could also add a flag to turn off tld scanning - for example if no JSPs are

used ( cocoon, velocity, etc ).



In future this should be extended to include a cache of the extension list ( scanned by the classloader ) and packages ( used to optimize loading ).



Rant:

This is one of the big errors in the JSP spec (IMO) - other java APIs use META-INF/services or the manifest so at least you read a single entry in a JAR. In JSP - you have to scan the entire META-INF dir, and look for all files with .tld extension. It is nice idea from developer perspective to be able to just drop jars - how you specify the descriptors is a problem.

Thursday, January 23, 2003

Load balancing in jk

Mladen Turk has proposed to use os load in jk2 load balancing. Finally. ( it has been proposed in the past - never implemented )

There are few details to clarify ( use backchannel or normal ajp or native RPC,

etc ), I'll update later.

Wednesday, January 22, 2003

Configurable TagPool in 50

The initial commit is in - seems to work. For configuration - I didn't have too many

choices, the JspServlet config was out of question, so this is the first use of

context init params .

is using precompiled JSPs - or knows how to set init params with jsp-page

The idea is to plug a different TagPool implementation and customize its parameters. The TagPool has a significant impact on JSP performance - and the user must be able to fine tune it and choose the right balance between memory use and speed.



I did few small optimizations in the default pool, and checked in the ThreadLocalPool - which has no sync, but keeps one pool per thread. If you have a JSP that has many tags and is very frequently accessed - it's worth trying it.



Configuration is done with init params for the context and servlet. Need to document it better - if it proves useful. I would try some JNDI - but it's too complex for my free time.

Using context params or JNDI for configuration

Jasper is configured using servlet init params, specified in web.xml. You can

customize per context - by defining a jsp servlet using a special name.

The problem: that would make your app unportable, it won't work with other jsp engines.



An alternative would be to use context params and init params of the

compiled servlet - with some special names that would be used by jasper.



Jasper would read global options from the context init params, then override

with local init params defined in the servlet (with jsp-page) tag. Options

names can be generic "jsp.keepgenerated" or "jasper.keepgenerated".



As API, we should _stop_ the use of Options interface ( and add a method for

every option we add ) and start using a simple getInitParam( String ). Or even better -

use JMX to push config options into the JSP engine ( which can be jasper or something else ).



There are many benefits:

* simpler configuration

* relatively portable - other engines can just ignore jasper settings. Right now

if you make per-context settings - the app won't work with other engines

* other engines may support same options

* it works very well for runtime options ( like what kind of thread pool to use )

* it works very well for precompiled JSPs ( which bypass JspServlet )

* general config tools can be used ( anything that supports web.xml config ), you

don't need jasper-specific GUI

* very easy and flexible



Another (probably) alternative is to use JNDI env entries. This is more powerfull -

as it allows the most flexibility in configuration, and is also supported

in the standard web.xml.



Possible naming conventions:

* java:env/PREFIX/SERVLET_NAME/JSP_OPTION - per page option, affects only a specific page

* java:env/PREFIX/global/JSP_OPTION - per context option, affects all pages ( unless overriden)

* /PREFIX2/jsp/JSP_OPTION - per server ( defined in server.xml ).



Another option - more powerfull if preffer a single config store ( LDAP, JDK1.4 prefs, etc ):

* /PREFIX1/INSTANCEID/VHOST/WEBAPP/PREFIX2/SERVLET_NAME/OPTIONS -> that will configure a specific instance

* global settings by using "Default" for different components.



PREFIX will avoid conflicts with other jndi entries. ( "options" ? )



Same mechanism can be used for the DefaultServlet, and also to set per context attributes

that are typically set in server.xml.



Future versions of the servlet spec - or de-facto standards - may define some cross-container

options ( jsp_keep_generated seems like a good one ).



The container should have control on allowing some options to be specified by individual apps -

probably the policy would do it ( it's already available if JNDI is used ).

Tuesday, January 21, 2003

SingleThreadedModel may be usefull

While doing the per/thread hacks on the JSP tag pool - and same for collecting statistics on per thread basis, to avoid sync - I just realized - the so bashed STM servlet may be actually one of the best things...



Of course, STM doesn't avoid the complexity of programing in a multithreaded environment - and it is probably even more vulnerable to errors. It is also much more complex to implement and harder to use. If you use STM, you must find ways to agregate the data from the multiple instances, and it may use more memory.



The big benefit is that with STM you basically get a per/thread worker - and do a lot of stuff with no sync calls. A good implementation would do a sync to get the STM - but that can be improved by using ThreadLocal or the new ThreadWithAttributes.



Not doing sync calls at runtime - or at least during the critical path - will have a visible impact on loaded sites ( if done right ). You have to pay for that in terms of complexity when you want to take the fields from all those servlet instances and

use them - that's where you may need sync and a lot of complex code.

Precompile the JSPs

All JSPs should be compiled. Using normal JSPs in development mode is normal - but I couldn't find any good reason why an application would not compile all JSPs.



Besides speed ( which is important ! ), you would also know about syntax errors

or missing dependencies. Most of the "jsp is slow" stuff is based on the first experience with a JSP page - where you have to wait for the HelloWorld.jsp to compile. A lot of "jsp is hard" is based on the same experience - when the compiler is not found.



It would be nice if a future version of the JSP spec would require ( or strongly recommend that ) as well as include a way to use the jsp-file tag togheter with servlet-class. I would like to be able to keep the jsp-file declaration next to the precompiled class name ( now only one can be specified - AFAIK ).



Update: I've got the admin/ precompiled - now you get a decent experience when using it. In process we found few bugs in jspc - I fixed it, but Hans had a better one.



As a bonus for using JSPC, the jsps will be visible in the JMX console - you'll

know the number of requets, average and max times and all the fun stuff. And you bypass the JspServlet - another (small according to Remy ) improvment. I did a small attempt to JMX-enable regular servlets - but it is too complicated and its

really not worth it - I'm more convinced than ever that JspServlet is the wrong way

to support Jsps.



JspInterceptor has its own problems - but now there is a better/cleaner way to abstract the JSP engine - just use JMX. The JSP engine should be just a JMX mbean, with a simple operation "compile( contextPath, jsp )". This can be crafted

on top of the existing JspC - and will insure consistent behavior. Regular JMX attributes will remove the confusion in jasper configuration, and it may even provide nice statistics ( compile time, number of errors, etc).



Probably I should split this entry in two ( or 3 ).

Friday, January 17, 2003

Classloader fun with JDK1.4

The issue is that with JDK1.4.1, if endorsed.dirs is set you may run into many kinds of weird classloading problems. Some classes in the CLASSPATH or in a loader will not be found, even if you place them in jre/lib/ext.



The problem goes away as soon as you remove endorsed.dirs. I still need to find out why is this happening - but for now I fixed jasper to work with crimson ( the parser in JDK1.4 ) and I use tomcat without endorsed.



Update: Remy has the same problem, this time JMX can't be loaded. There is only one solution - stop using endorsed.dirs until Sun fixes it.



Update: It seems one ClassPath attribute in a jar included in endorsed was referencing other jars, and removing that fixes some of the problems. Still - endorsed is supposed to override a number of packages, it shouldn't affect the others.

Thursday, January 16, 2003

More JMX in tomcat5

Finally added thread information ( including what each thread is doing ), request info, servlet execution times, etc. The context and servlet now use JSR77 names.



I'm not sure if the naming for the other components is very good - but at least all jk and coyote components are exposed and may be controlled/viewed. I started to switch to NamingListener for callback inside jk - it should be easy to do, but I want to also get rid of JkMain and use JMX to put the components togheter.

Tuesday, January 14, 2003

Extension points in tomcat5

My search for the ideal extension/hook/callback mechanism is over. After many months ( or years - if I count the many variations on Interceptors and 3.2 refactorings ) of search, I give up on the combined Valve/Interceptor and any other variation.



All tomcat developers seem to agree that JMX is the "right" solution to configure and manage the components inside tomcat. I believe JMX notification is the "right" solution for extension points and callbacks.



The benefits seem clear:

* a clean, simple, well documented and unlikely to change model.

* it'll be easy to know what notification a component sends and what notifications a component handles ( using JMX metadata )

* consistent configuration

* one simple and neutral interface - completely independent of tomcat internals



The only problem is that the notification model doesn't support the Valve - but instead of trying to support both Valve and Interceptor, we should just keep Valves around for all modules that need this kind of functionality.

Monday, January 13, 2003

UserDatabase needs changes

Every time I look at the JMX console I remind myself that UserDatabase needs to be fixed before Tomcat5 is shiped. It is just very wrong - you can't scale if all users are in memory, and JMX will become useless if you have 1 mbean for each user.



If UserDatabase returns a simple Hashtable with the user info - it would be quite easy to use JSP-EL to display and manipulate the info. The ideal solution is to turn UserDatabase into a JNDI DirContext - but I'm not even 1/2 way with the JNDI proposal.

Friday, January 10, 2003

JMX support in ThreadPool

Few notes on the JMX-enabled ThreadPool effort.



The goal is to see what the pool and each thread is doing - and maybe stop hunged threads.



First, the thread pool itself should provide basic info - how many thread are active, how many threads died. Changing parameters ( increasing maxthreads ) at runtime is tricky - we avoid sync for performance, so we'll probably need to create a new array and switch.



The second issue is information about what's each thread doing. Currently I'm using ThreadWithAttributes - so we can just cast and have O(1) access to attributes. I already changed Http and Jk connectors to provide info about the stage and current request. I implemented the changes - seems ok, but need to cleanup before committing it.



One issue is security. Right now a guard is used ( the ThreadPool for now ), and only components that have access to it can read/write. JMX policy protection will be vital - and we need to find ways to protect if the SecurityManager is not enabled. With the current code, if user code gets access to JMX it can see what

all other threads are doing - a problem for web hosting environments.





Update:



Done. You can use it with any tomcat version ( if j-t-c is built from HEAD ). The name is "DOMAIN:type=ThreadPool,worker=http,name=http%8080" and

"DOMAIN:type=ThreadPool,worker=jk,name=0.0.0.0%8009" ( the local part needs cleanup ).



What is available is the string version (threadStatusString) and 2 String[] with the

current status ( parsing, service, ended, etc ) and last request. More info is collected per request, in RequestProcessors object ( bytes sent, etc ).

Since we may have a lot of threads, there is a single manageable object that controls all threads in a pool ( corresponding to the ThreadPoolMX )



Open issue: should we treat "status" as pure informative and let servlets set it ? Long running servlets could provide some debugging info.