org.directwebremoting.impl
Class DefaultServerLoadMonitor

java.lang.Object
  extended by org.directwebremoting.impl.AbstractServerLoadMonitor
      extended by org.directwebremoting.impl.DefaultServerLoadMonitor
All Implemented Interfaces:
ServerLoadMonitor

public class DefaultServerLoadMonitor
extends AbstractServerLoadMonitor
implements ServerLoadMonitor

A smart implementation of ServerLoadMonitor.

What a browser does:

       connected disconnected connected ...
      ____________          ____________
      |          |          |          |
      |          |          |          |
 _____|          |__________|          |______
       [---cT---] [---dT---] [---cT---] ...
 

Where cT is the connectedTime and dT is the disconnectedTime.

We impose some limits: a maximum number of symultaneously connected browsers maxWaitingThreads, and the maximum number of connections per second maxHitsPerSecond.

We attempt to keep the actual waitingThreads and hitsPerSecond within bounds by vairying connectedTime and disconnectedTime.

The system is in one of 3 modes: USAGE_LOW, USAGE_HIGH and USAGE_DIGG. The boundary between USAGE_LOW and USAGE_HIGH is called threadOut. The boundary between USAGE_HIGH and USAGE_DIGG is called hitOut.

The system starts in USAGE_LOW mode. This mode uses constant values of connectedTime=60 secs and disconnectedTime=0 secs. We could use much bigger values for connectedTime (like infinite) however the servlet spec does not enable servlet engines to inform us if the browser goes away so we check by asking the browser to reconnect periodically.

In USAGE_LOW mode we measure the number of clients using the number of concurrently connected browsers (waitingThreads), when this goes above maxWaitingThreads we move into USAGE_HIGH mode.

On entering USAGE_HIGH mode, the settings (initially) change to connectedTime=49 secs and disconnectedTime=1 sec. As the load increases the connectedTime decreases linearly from 49 secs down to prevent the hits per second from going above maxHitsPerSecond. If the connectedTime goes below 1sec then the mode switches to USAGE_DIGG. If the connectedTime goes above 49 secs then mode switches to USAGE_LOW.

Note: there is some danger of an overlap where the system toggles between USAGE_HIGH and USAGE_LOW. We need some way to prevent this from happening.

On entering USAGE_DIGG mode, the connectedTime changes to 0 secs, and the disconnectedTime changes to 2 secs (to keep the round trip time at 2 secs). The disconnectedTime alters to prevent the hitsPerSecond from going above maxHitsPerSecond (In USAGE_HIGH mode the connectedTime was altered). When the disconnectedTime would go under 2 secs, we switch back to USAGE_HIGH mode.

Author:
Joe Walker [joe at getahead dot org]

Field Summary
protected  int connectedTime
          The time we are currently waiting before sending a browser away and asking it to reconnect.
protected  int disconnectedTime
          How long are we telling users to wait before they come back next
protected  HitMonitor hitMonitor
          Our record of the server loading
protected static int hitOutRoundTripTime
           
protected  int maxConnectedTime
          Static configuration data: What is the longest we wait for extra input after detecting output.
protected  int maxHitsPerSecond
          Static configuration data: The max number of hits per second.
protected  int maxWaitingThreads
          Static configuration data: The max number of threads we keep waiting.
protected  int mode
          What is the current usage mode.
protected static int SECONDS_MONITORED
          We are recording the number of hits in the last 5 seconds.
protected static int threadOutRoundTripTime
           
protected static int USAGE_DIGG
          The system is very heavily used, polling only.
protected static int USAGE_HIGH
          This system can't cope with everyone on comet, we are in mixed mode.
protected static int USAGE_LOW
          The system is under-utilized.
protected static java.lang.String[] USAGE_NAMES
          Some Strings to help us give some debug output
protected static int usageDiggConnectedTime
           
protected static int usageDiggMinDisconnectedTime
           
protected static int usageHighDisconnectedTime
           
protected static int usageHighFinalConnectedTime
           
protected static int usageHighInitialConnectedTime
           
protected  int waitingThreads
          How many sleepers are there?
 
Fields inherited from class org.directwebremoting.impl.AbstractServerLoadMonitor
waitControllers
 
Constructor Summary
DefaultServerLoadMonitor()
           
 
Method Summary
 long getConnectedTime()
          What's the longest time that we should wait before asking the client to reconnect?
 int getDisconnectedTime()
          Controller for poll times.
 void setMaxHitsPerSecond(int maxHitsPerSecond)
           
 void setMaxWaitingThreads(int maxWaitingThreads)
           
protected  void setMode(int mode)
          For debug purposes we keep a track of what mode we are in.
 boolean supportsStreaming()
          If the server is not going to be streaming then we need to tell browsers to just use XHR rather than anything fancier.
 void threadWaitEnding(WaitController controller)
          A thread has just ended a wait period.
 void threadWaitStarting(WaitController controller)
          A thread is about to begin a wait period.
 
Methods inherited from class org.directwebremoting.impl.AbstractServerLoadMonitor
shutdown, shutdownRandomWaitControllers
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface org.directwebremoting.extend.ServerLoadMonitor
shutdown
 

Field Detail

usageHighDisconnectedTime

protected static final int usageHighDisconnectedTime
See Also:
Constant Field Values

usageHighInitialConnectedTime

protected static final int usageHighInitialConnectedTime
See Also:
Constant Field Values

usageHighFinalConnectedTime

protected static final int usageHighFinalConnectedTime
See Also:
Constant Field Values

usageDiggConnectedTime

protected static final int usageDiggConnectedTime
See Also:
Constant Field Values

usageDiggMinDisconnectedTime

protected static final int usageDiggMinDisconnectedTime
See Also:
Constant Field Values

hitOutRoundTripTime

protected static final int hitOutRoundTripTime
See Also:
Constant Field Values

threadOutRoundTripTime

protected static final int threadOutRoundTripTime
See Also:
Constant Field Values

maxWaitingThreads

protected int maxWaitingThreads
Static configuration data: The max number of threads we keep waiting. We reduce the timeWithinPoll*Stream variables to reduce the load


maxHitsPerSecond

protected int maxHitsPerSecond
Static configuration data: The max number of hits per second. We increase the poll time to compensate and reduce the load. If this number is not at least half maxWaitingThreads then the USAGE_HIGH mode will not exist and the system will sublime from USAGE_LOW to USAGE_DIGG


maxConnectedTime

protected int maxConnectedTime
Static configuration data: What is the longest we wait for extra input after detecting output.


USAGE_LOW

protected static final int USAGE_LOW
The system is under-utilized. Everyone does comet.

See Also:
Constant Field Values

USAGE_HIGH

protected static final int USAGE_HIGH
This system can't cope with everyone on comet, we are in mixed mode.

See Also:
Constant Field Values

USAGE_DIGG

protected static final int USAGE_DIGG
The system is very heavily used, polling only.

See Also:
Constant Field Values

USAGE_NAMES

protected static final java.lang.String[] USAGE_NAMES
Some Strings to help us give some debug output


mode

protected int mode
What is the current usage mode.


connectedTime

protected int connectedTime
The time we are currently waiting before sending a browser away and asking it to reconnect.


disconnectedTime

protected int disconnectedTime
How long are we telling users to wait before they come back next


SECONDS_MONITORED

protected static final int SECONDS_MONITORED
We are recording the number of hits in the last 5 seconds. Maybe we should think about making this configurable.

See Also:
Constant Field Values

hitMonitor

protected HitMonitor hitMonitor
Our record of the server loading


waitingThreads

protected int waitingThreads
How many sleepers are there?

Constructor Detail

DefaultServerLoadMonitor

public DefaultServerLoadMonitor()
Method Detail

supportsStreaming

public boolean supportsStreaming()
Description copied from interface: ServerLoadMonitor
If the server is not going to be streaming then we need to tell browsers to just use XHR rather than anything fancier.

Specified by:
supportsStreaming in interface ServerLoadMonitor
Returns:
true if the server will be supporting streaming

getConnectedTime

public long getConnectedTime()
Description copied from interface: ServerLoadMonitor
What's the longest time that we should wait before asking the client to reconnect?

Specified by:
getConnectedTime in interface ServerLoadMonitor
Returns:
The maximum client connected time

getDisconnectedTime

public int getDisconnectedTime()
Description copied from interface: ServerLoadMonitor
Controller for poll times.

TODO: We should probably get rid of this and leave it to PollHandler?

Specified by:
getDisconnectedTime in interface ServerLoadMonitor
Returns:
How long should this client wait until it next polls?

threadWaitStarting

public void threadWaitStarting(WaitController controller)
Description copied from interface: ServerLoadMonitor
A thread is about to begin a wait period. This can be used by implementations to dynamically adjust the poll timings.

Specified by:
threadWaitStarting in interface ServerLoadMonitor
Overrides:
threadWaitStarting in class AbstractServerLoadMonitor
Parameters:
controller - An object that we can use to control the wait

threadWaitEnding

public void threadWaitEnding(WaitController controller)
Description copied from interface: ServerLoadMonitor
A thread has just ended a wait period. This can be used by implementations to dynamically adjust the poll timings.

Specified by:
threadWaitEnding in interface ServerLoadMonitor
Overrides:
threadWaitEnding in class AbstractServerLoadMonitor
Parameters:
controller - An object that we can use to control the wait

setMode

protected void setMode(int mode)
For debug purposes we keep a track of what mode we are in.

Parameters:
mode - The new usage mode

setMaxWaitingThreads

public void setMaxWaitingThreads(int maxWaitingThreads)
Parameters:
maxWaitingThreads - the maxWaitingThreads to set

setMaxHitsPerSecond

public void setMaxHitsPerSecond(int maxHitsPerSecond)
Parameters:
maxHitsPerSecond - the maxHitsPerSecond to set