292814 used filter/servlet name for managed attribute

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@1928 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Greg Wilkins 2010-06-06 23:34:19 +00:00
parent 41884b613c
commit 3e70a7f7ac
5 changed files with 90 additions and 79 deletions

View File

@ -79,6 +79,13 @@ import org.eclipse.jetty.util.resource.Resource;
public class ContextHandler extends ScopedHandler implements Attributes, Server.Graceful
{
private static final ThreadLocal<Context> __context=new ThreadLocal<Context>();
/**
* If a context attribute with this name is set, it is interpreted as a
* comma separated list of attribute name. Any other context attributes that
* are set with a name from this list will result in a call to {@link #setManagedAttribute(String, Object)},
* which typically initiates the creation of a JMX MBean for the attribute value.
*/
public static final String MANAGED_ATTRIBUTES = "org.eclipse.jetty.server.context.ManagedAttributes";
/* ------------------------------------------------------------ */
@ -618,7 +625,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
String name = (String)e.nextElement();
Object value = _scontext.getAttribute(name);
setManagedAttribute(name,value);
checkManagedAttribute(name,value);
}
}
@ -682,7 +689,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
while(e.hasMoreElements())
{
String name = (String)e.nextElement();
setManagedAttribute(name,null);
checkManagedAttribute(name,null);
}
}
finally
@ -999,7 +1006,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
*/
public void removeAttribute(String name)
{
setManagedAttribute(name,null);
checkManagedAttribute(name,null);
_attributes.removeAttribute(name);
}
@ -1012,7 +1019,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
*/
public void setAttribute(String name, Object value)
{
setManagedAttribute(name,value);
checkManagedAttribute(name,value);
_attributes.setAttribute(name,value);
}
@ -1029,7 +1036,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
while (e.hasMoreElements())
{
String name = (String)e.nextElement();
setManagedAttribute(name,attributes.getAttribute(name));
checkManagedAttribute(name,attributes.getAttribute(name));
}
}
else
@ -1040,7 +1047,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
String name = (String)e.nextElement();
Object value=attributes.getAttribute(name);
setManagedAttribute(name,value);
checkManagedAttribute(name,value);
_attributes.setAttribute(name,value);
}
}
@ -1053,26 +1060,26 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
while (e.hasMoreElements())
{
String name = (String)e.nextElement();
setManagedAttribute(name,null);
checkManagedAttribute(name,null);
}
_attributes.clearAttributes();
}
/* ------------------------------------------------------------ */
private void setManagedAttribute(String name, Object value)
public void checkManagedAttribute(String name, Object value)
{
if (_managedAttributes!=null && _managedAttributes.containsKey(name))
{
Object old =_managedAttributes.put(name,value);
if (old!=null)
getServer().getContainer().removeBean(old);
if (value!=null)
{
if (_logger.isDebugEnabled()) _logger.debug("Managing "+name);
getServer().getContainer().addBean(value);
}
setManagedAttribute(name,value);
}
}
/* ------------------------------------------------------------ */
public void setManagedAttribute(String name, Object value)
{
Object old =_managedAttributes.put(name,value);
getServer().getContainer().update(this,old,value,name);
}
/* ------------------------------------------------------------ */
/**
@ -1753,7 +1760,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
return;
}
setManagedAttribute(name,value);
checkManagedAttribute(name,value);
Object old_value=_contextAttributes.getAttribute(name);
if (value==null)
@ -1786,7 +1793,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
*/
public synchronized void removeAttribute(String name)
{
setManagedAttribute(name,null);
checkManagedAttribute(name,null);
if (_contextAttributes==null)
{

View File

@ -37,6 +37,7 @@ import javax.servlet.http.HttpSessionBindingListener;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.thread.Timeout;
@ -60,35 +61,53 @@ import org.eclipse.jetty.util.thread.Timeout;
* The {@link #extractUserId(ServletRequest request)} function should be
* implemented, in order to uniquely identify authenticated users.
* <p>
* The following init parameters control the behavior of the filter:
* The following init parameters control the behavior of the filter:<dl>
*
* maxRequestsPerSec the maximum number of requests from a connection per
* <dt>maxRequestsPerSec</dt>
* <dd>the maximum number of requests from a connection per
* second. Requests in excess of this are first delayed,
* then throttled.
* then throttled.</dd>
*
* delayMs is the delay given to all requests over the rate limit,
* <dt>delayMs</dt>
* <dd>is the delay given to all requests over the rate limit,
* before they are considered at all. -1 means just reject request,
* 0 means no delay, otherwise it is the delay.
* 0 means no delay, otherwise it is the delay.</dd>
*
* maxWaitMs how long to blocking wait for the throttle semaphore.
* <dt>maxWaitMs</dt>
* <dd>how long to blocking wait for the throttle semaphore.</dd>
*
* throttledRequests is the number of requests over the rate limit able to be
* considered at once.
* <dt>throttledRequests</dt>
* <dd>is the number of requests over the rate limit able to be
* considered at once.</dd>
*
* throttleMs how long to async wait for semaphore.
* <dt>throttleMs</dt>
* <dd>how long to async wait for semaphore.</dd>
*
* maxRequestMs how long to allow this request to run.
* <dt>maxRequestMs</dt>
* <dd>how long to allow this request to run.</dd>
*
* maxIdleTrackerMs how long to keep track of request rates for a connection,
* before deciding that the user has gone away, and discarding it
* <dt>maxIdleTrackerMs</dt>
* <dd>how long to keep track of request rates for a connection,
* before deciding that the user has gone away, and discarding it</dd>
*
* insertHeaders if true , insert the DoSFilter headers into the response. Defaults to true.
* <dt>insertHeaders</dt>
* <dd>if true , insert the DoSFilter headers into the response. Defaults to true.</dd>
*
* trackSessions if true, usage rate is tracked by session if a session exists. Defaults to true.
* <dt>trackSessions</dt>
* <dd>if true, usage rate is tracked by session if a session exists. Defaults to true.</dd>
*
* remotePort if true and session tracking is not used, then rate is tracked by IP+port (effectively connection). Defaults to false.
* <dt>remotePort</dt>
* <dd>if true and session tracking is not used, then rate is tracked by IP+port (effectively connection). Defaults to false.</dd>
*
* ipWhitelist a comma-separated list of IP addresses that will not be rate limited
* <dt>ipWhitelist</dt>
* <dd>a comma-separated list of IP addresses that will not be rate limited</dd>
*
* <dt>managedAttr</dt>
* <dd>if set to true, then this servlet is set as a {@link ServletContext} attribute with the
* filter name as the attribute name. This allows context external mechanism (eg JMX via {@link ContextHandler#MANAGED_ATTRIBUTES}) to
* manage the configuration of the filter.</dd>
* </dl>
* </p>
*/
public class DoSFilter implements Filter
@ -96,7 +115,6 @@ public class DoSFilter implements Filter
final static String __TRACKER = "DoSFilter.Tracker";
final static String __THROTTLED = "DoSFilter.Throttled";
final static String __DEFAULT_ATTR_PREFIX = "DoSFilter";
final static int __DEFAULT_MAX_REQUESTS_PER_SEC = 25;
final static int __DEFAULT_DELAY_MS = 100;
final static int __DEFAULT_THROTTLE = 5;
@ -105,7 +123,7 @@ public class DoSFilter implements Filter
final static long __DEFAULT_MAX_REQUEST_MS_INIT_PARAM=30000L;
final static long __DEFAULT_MAX_IDLE_TRACKER_MS_INIT_PARAM=30000L;
final static String ATTR_PREFIX_INIT_PARAM = "attrPrefix";
final static String MANAGED_ATTR_INIT_PARAM="managedAttr";
final static String MAX_REQUESTS_PER_S_INIT_PARAM = "maxRequestsPerSec";
final static String DELAY_MS_INIT_PARAM = "delayMs";
final static String THROTTLED_REQUESTS_INIT_PARAM = "throttledRequests";
@ -154,11 +172,6 @@ public class DoSFilter implements Filter
{
_context = filterConfig.getServletContext();
String attrPrefix = __DEFAULT_ATTR_PREFIX;
if (filterConfig.getInitParameter(ATTR_PREFIX_INIT_PARAM)!=null)
attrPrefix=filterConfig.getInitParameter(ATTR_PREFIX_INIT_PARAM);
_name = attrPrefix;
_queue = new Queue[getMaxPriority() + 1];
_listener = new ContinuationListener[getMaxPriority() + 1];
for (int p = 0; p < _queue.length; p++)
@ -275,10 +288,8 @@ public class DoSFilter implements Filter
});
_timerThread.start();
if (_context!=null)
{
_context.setAttribute("org.eclipse.jetty.servlets."+_name,this);
}
if (_context!=null && Boolean.parseBoolean(filterConfig.getInitParameter(MANAGED_ATTR_INIT_PARAM)))
_context.setAttribute(filterConfig.getFilterName(),this);
}

View File

@ -60,9 +60,7 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
* the web application.
* <p>
* To facilitate JMX monitoring, the "HttpClient", it's "ThreadPool" and the "Logger"
* are set as context attributes prefixed with "org.eclipse.jetty.servlets."+name
* (unless otherwise set with attrPrefix). This attribute prefix is also used for the
* logger name.
* are set as context attributes prefixed with the servlet name.
* <p>
* The following init parameters may be used to configure the servlet: <ul>
* <li>name - Name of Proxy servlet (default: "ProxyServlet"
@ -92,7 +90,6 @@ public class ProxyServlet implements Servlet
protected ServletConfig _config;
protected ServletContext _context;
protected String _name="ProxyServlet";
/* ------------------------------------------------------------ */
/* (non-Javadoc)
@ -111,17 +108,14 @@ public class ProxyServlet implements Servlet
try
{
String t = config.getInitParameter("attrPrefix");
if (t!=null)
_name=t;
_log= Log.getLogger("org.eclipse.jetty.servlets."+_name);
_log= Log.getLogger("org.eclipse.jetty.servlets."+config.getServletName());
t = config.getInitParameter("maxThreads");
String t = config.getInitParameter("maxThreads");
if (t!=null)
_client.setThreadPool(new QueuedThreadPool(Integer.parseInt(t)));
else
_client.setThreadPool(new QueuedThreadPool());
((QueuedThreadPool)_client.getThreadPool()).setName(_name.substring(_name.lastIndexOf('.')+1));
((QueuedThreadPool)_client.getThreadPool()).setName(config.getServletName());
t = config.getInitParameter("maxConnections");
if (t!=null)
@ -131,9 +125,9 @@ public class ProxyServlet implements Servlet
if (_context!=null)
{
_context.setAttribute("org.eclipse.jetty.servlets."+_name+".Logger",_log);
_context.setAttribute("org.eclipse.jetty.servlets."+_name+".ThreadPool",_client.getThreadPool());
_context.setAttribute("org.eclipse.jetty.servlets."+_name+".HttpClient",_client);
_context.setAttribute(config.getServletName()+".Logger",_log);
_context.setAttribute(config.getServletName()+".ThreadPool",_client.getThreadPool());
_context.setAttribute(config.getServletName()+".HttpClient",_client);
}
}
catch (Exception e)
@ -513,7 +507,7 @@ public class ProxyServlet implements Servlet
if (!_prefix.startsWith("/"))
throw new UnavailableException("Prefix parameter must start with a '/'.");
_log.info(_name + " @ " + _prefix + " to " + _proxyTo);
_log.info(config.getServletName()+" @ " + _prefix + " to " + _proxyTo);
}
@Override

View File

@ -33,7 +33,7 @@ import javax.servlet.http.HttpSession;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.server.handler.ContextHandler;
/**
* Quality of Service Filter.
@ -42,14 +42,14 @@ import org.eclipse.jetty.util.log.Log;
* If more requests are received, they are suspended and placed on priority queues. Priorities are determined by
* the {@link #getPriority(ServletRequest)} method and are a value between 0 and the value given by the "maxPriority"
* init parameter (default 10), with higher values having higher priority.
* <p>
* </p><p>
* This filter is ideal to prevent wasting threads waiting for slow/limited
* resources such as a JDBC connection pool. It avoids the situation where all of a
* containers thread pool may be consumed blocking on such a slow resource.
* By limiting the number of active threads, a smaller thread pool may be used as
* the threads are not wasted waiting. Thus more memory may be available for use by
* the active threads.
* <p>
* </p><p>
* Furthermore, this filter uses a priority when resuming waiting requests. So that if
* a container is under load, and there are many requests waiting for resources,
* the {@link #getPriority(ServletRequest)} method is used, so that more important
@ -57,24 +57,27 @@ import org.eclipse.jetty.util.log.Log;
* maxRequest limit slightly smaller than the containers thread pool and a high priority
* allocated to admin users. Thus regardless of load, admin users would always be
* able to access the web application.
* <p>
* </p><p>
* The maxRequest limit is policed by a {@link Semaphore} and the filter will wait a short while attempting to acquire
* the semaphore. This wait is controlled by the "waitMs" init parameter and allows the expense of a suspend to be
* avoided if the semaphore is shortly available. If the semaphore cannot be obtained, the request will be suspended
* for the default suspend period of the container or the valued set as the "suspendMs" init parameter.
*
* </p><p>
* If the "managedAttr" init parameter is set to true, then this servlet is set as a {@link ServletContext} attribute with the
* filter name as the attribute name. This allows context external mechanism (eg JMX via {@link ContextHandler#MANAGED_ATTRIBUTES}) to
* manage the configuration of the filter.
* </p>
*
*
*/
public class QoSFilter implements Filter
{
final static String __DEFAULT_ATTR_PREFIX="QoSFilter";
final static int __DEFAULT_MAX_PRIORITY=10;
final static int __DEFAULT_PASSES=10;
final static int __DEFAULT_WAIT_MS=50;
final static long __DEFAULT_TIMEOUT_MS = -1;
final static String ATTR_PREFIX_INIT_PARAM="attrPrefix";
final static String MANAGED_ATTR_INIT_PARAM="managedAttr";
final static String MAX_REQUESTS_INIT_PARAM="maxRequests";
final static String MAX_PRIORITY_INIT_PARAM="maxPriority";
final static String MAX_WAIT_INIT_PARAM="waitMs";
@ -82,7 +85,6 @@ public class QoSFilter implements Filter
ServletContext _context;
protected String _name;
protected long _waitMs;
protected long _suspendMs;
protected int _maxRequests;
@ -90,7 +92,7 @@ public class QoSFilter implements Filter
private Semaphore _passes;
private Queue<Continuation>[] _queue;
private ContinuationListener[] _listener;
private String _suspended=__DEFAULT_ATTR_PREFIX+"@"+this.hashCode();
private String _suspended="QoSFilter@"+this.hashCode();
/* ------------------------------------------------------------ */
/**
@ -99,11 +101,6 @@ public class QoSFilter implements Filter
public void init(FilterConfig filterConfig)
{
_context=filterConfig.getServletContext();
String attrPrefix = __DEFAULT_ATTR_PREFIX;
if (filterConfig.getInitParameter(ATTR_PREFIX_INIT_PARAM)!=null)
attrPrefix = filterConfig.getInitParameter(ATTR_PREFIX_INIT_PARAM);
_name = attrPrefix;
int max_priority=__DEFAULT_MAX_PRIORITY;
if (filterConfig.getInitParameter(MAX_PRIORITY_INIT_PARAM)!=null)
@ -142,11 +139,9 @@ public class QoSFilter implements Filter
if (filterConfig.getInitParameter(SUSPEND_INIT_PARAM)!=null)
suspend=Integer.parseInt(filterConfig.getInitParameter(SUSPEND_INIT_PARAM));
_suspendMs=suspend;
if (_context!=null)
{
_context.setAttribute("org.eclipse.jetty.servlets."+_name,this);
}
if (_context!=null && Boolean.parseBoolean(filterConfig.getInitParameter(MANAGED_ATTR_INIT_PARAM)))
_context.setAttribute(filterConfig.getFilterName(),this);
}
/* ------------------------------------------------------------ */

View File

@ -9,7 +9,7 @@
<context-param>
<param-name>org.eclipse.jetty.server.context.ManagedAttributes</param-name>
<param-value>org.eclipse.jetty.servlets.ProxyServlet.Logger,org.eclipse.jetty.servlets.ProxyServlet.ThreadPool,org.eclipse.jetty.servlets.ProxyServlet.HttpClient</param-value>
<param-value>QoSFilter,TransparentProxy.Logger,TransparentProxy.ThreadPool,TransparentProxy.HttpClient</param-value>
</context-param>
<!-- Declare TestListener, which declares TestFilter -->
@ -38,6 +38,10 @@
<param-name>maxRequests</param-name>
<param-value>20</param-value>
</init-param>
<init-param>
<param-name>managedAttr</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>QoSFilter</filter-name>