001: /*
002: * Copyright 2005 Joe Walker
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.directwebremoting.impl;
017:
018: import org.directwebremoting.extend.ServerLoadMonitor;
019: import org.directwebremoting.extend.WaitController;
020: import org.directwebremoting.util.HitMonitor;
021:
022: /**
023: * A smart implementation of ServerLoadMonitor, customized for Jetty.
024: * The ThreadDroppingServerLoadMonitor attempts to keep the hit rate down by increasing
025: * the disconnected time as usage increases.
026: * @author Joe Walker [joe at getahead dot org]
027: */
028: public class ThreadDroppingServerLoadMonitor extends
029: AbstractServerLoadMonitor implements ServerLoadMonitor {
030: /* (non-Javadoc)
031: * @see org.directwebremoting.extend.ServerLoadMonitor#supportsStreaming()
032: */
033: public boolean supportsStreaming() {
034: return true;
035: }
036:
037: /* (non-Javadoc)
038: * @see org.directwebremoting.extend.ServerLoadMonitor#getConnectedTime()
039: */
040: public long getConnectedTime() {
041: return connectedTime;
042: }
043:
044: /* (non-Javadoc)
045: * @see org.directwebremoting.ServerLoadMonitor#timeToNextPoll()
046: */
047: public int getDisconnectedTime() {
048: return disconnectedTime;
049: }
050:
051: /* (non-Javadoc)
052: * @see org.directwebremoting.impl.AbstractServerLoadMonitor#threadWaitStarting(org.directwebremoting.extend.WaitController)
053: */
054: @Override
055: public void threadWaitStarting(WaitController controller) {
056: hitMonitor.recordHit();
057: super .threadWaitStarting(controller);
058:
059: checkLoading();
060: }
061:
062: /* (non-Javadoc)
063: * @see org.directwebremoting.impl.AbstractServerLoadMonitor#threadWaitEnding(org.directwebremoting.extend.WaitController)
064: */
065: @Override
066: public void threadWaitEnding(WaitController controller) {
067: super .threadWaitEnding(controller);
068: }
069:
070: /**
071: * Check that we are setting the time to next poll correctly.
072: */
073: private void checkLoading() {
074: float hitsPerSecond = (float) hitMonitor.getHitsInLastPeriod()
075: / SECONDS_MONITORED;
076:
077: // If we're getting close to the upper bound then slow down
078: float load = hitsPerSecond / maxHitsPerSecond;
079:
080: disconnectedTime = (int) (disconnectedTime * load);
081: if (disconnectedTime == 0) {
082: disconnectedTime = 1;
083: }
084: }
085:
086: /**
087: * @param maxHitsPerSecond the maxHitsPerSecond to set
088: */
089: public void setMaxHitsPerSecond(int maxHitsPerSecond) {
090: this .maxHitsPerSecond = maxHitsPerSecond;
091: }
092:
093: /**
094: * Static configuration data: The max number of hits per second.
095: * We increase the poll time to compensate and reduce the load. If this
096: * number is not at least half maxWaitingThreads then the USAGE_HIGH mode
097: * will not exist and the system will sublime from USAGE_LOW to USAGE_DIGG
098: */
099: protected int maxHitsPerSecond = 100;
100:
101: /**
102: * The time we are currently waiting before sending a browser away and
103: * asking it to reconnect.
104: */
105: protected int connectedTime = 60000;
106:
107: /**
108: * How long are we telling users to wait before they come back next
109: */
110: protected int disconnectedTime = 1;
111:
112: /**
113: * We are recording the number of hits in the last 5 seconds.
114: * Maybe we should think about making this configurable.
115: */
116: protected static final int SECONDS_MONITORED = 10;
117:
118: /**
119: * Our record of the server loading
120: */
121: protected HitMonitor hitMonitor = new HitMonitor(SECONDS_MONITORED);
122: }
|