Merge remote-tracking branch 'origin/jetty-9.3.x' into jetty-9.4.x

This commit is contained in:
Greg Wilkins 2016-05-05 11:37:00 +10:00
commit 15480a7c94
7 changed files with 183 additions and 125 deletions

View File

@ -23,13 +23,12 @@ The link:#quickstart-config-what[next section] gives an overview of the action c
==== Jetty POJO Configuration
The core components of Jetty are simply Plain Old Java Objects (http://en.wikipedia.org/wiki/Plain_Old_Java_Object[POJOs]); the process of configuring Jetty is mostly the process of instantiating, assembling and setting fields on the Jetty POJOs.
You can achieve this either by:
The core components of Jetty are Plain Old Java Objects (http://en.wikipedia.org/wiki/Plain_Old_Java_Object[POJOs]); the process of configuring Jetty is mostly the process of instantiating, assembling and setting fields on the Jetty POJOs.
This can be achieved by:
* Writing Java code to directly instantiate and assemble Jetty objects. This is referred to as xref:embedding-jetty[].
* Using Jetty XML configuration, which is an http://en.wikipedia.org/wiki/Inversion_of_Control[Inversion of Control
(IoC)] framework, to instantiate and assemble Jetty objects as XML objects.
The `etc/jetty.xml` file is the main Jetty XML configuration file, but there are many other `etc/jetty-`__feature__`.xml` files included in the jetty distribution.
* Using Jetty XML configuration, which is an http://en.wikipedia.org/wiki/Inversion_of_Control[Inversion of Control (IoC)] framework, to instantiate and assemble Jetty objects as XML objects.
The `etc/jetty.xml` file is the main Jetty XML configuration file, but there are many other `etc/jetty-`__feature__`.xml` files included in the Jetty distribution.
* Using a third party http://en.wikipedia.org/wiki/Inversion_of_Control[IoC] framework like http://en.wikipedia.org/wiki/Spring_Framework[Spring], to instantiate and assemble Jetty objects as Spring beans.
Because the main Jetty configuration is done by IoC, the link:{JDURL}/[Jetty API documentation] is the ultimate configuration reference.
@ -42,67 +41,64 @@ The Jetty distribution uses the following configuration files to instantiate, in
The Jetty Start mechanism uses the command line, the `$JETTY_BASE/start.ini` and/or `$JETTY_BASE/start.d/*.ini` files to create an effective command line of arguments.
Arguments may be:
* XML files in Jetty IoC (or spring) XML format
* Module activations in the form --module=name
* Property in the form of name=value, used to parameterize Jetty IoC XML
* XML files in Jetty IoC (or Spring) XML format
* Module activations in the form `--module=name`
* Property in the form of `name=value`, used to parameterize Jetty IoC XML
* A standard http://en.wikipedia.org/wiki/Java_properties[Java property file] containing additional start properties
* Other start.jar options (see java -jar start.jar --help)
* Some JVM options
* Other start.jar options (see `java -jar start.jar --help`)
* Some JVM options in combination with `--exec`, such as `-Xbootclasspath`.
+
It is the ini files are located in the jetty base (if different from jetty home) that are typically edited to change the configuration (Eg change ports)
It is the `ini` files located in the Jetty base directory (if different from Jetty home) that are typically edited to change the configuration (e.g. change ports).
mod files::
The `$JETTY_HOME/modules/*.mod` files contain the definition of modules that can be activated by --module=name.
Each mod file defines:
`mod files`::
The `$JETTY_HOME/modules/*.mod` files contain the definition of modules that can be activated by ``--module=name`.
Each `mod` file defines:
* Module dependencies for ordering and activation
* The libraries needed by the module to be added to the classpath
* The libraries needed by the module to be added to the `classpath`
* The XML files needed by the module to be added to the effective command line
* Files needed by the activated module
* A template ini file to be used when activating with the --add-to-start=name option
* A template `ini` file to be used when activating the `--add-to-start=name` option
+
Typically module files are rarely edited and only for significant structural changes.
The *.mod files are normally located `$JETTY_HOME/modules/`, but extra or edited modules may be added to `$JETTY_BASE/module`.
If module changes are required, it is best practice to copy the particular *.mod file from `$JETTY_HOME/modules/` to `$JETTY_BASE/modules/` before being modified.
Typically module files are rarely edited and only then for significant structural changes.
The `*.mod` files are normally located in `$JETTY_HOME/modules/`, but extra or edited modules may be added to `$JETTY_BASE/module`.
If module changes are required, it is best practice to copy the particular `*.mod` file from `$JETTY_HOME/modules/` to `$JETTY_BASE/modules/` before being modified.
XML files::
XML files in link:#jetty-xml-syntax[Jetty IoC XML format] or spring IoC format are listed either on the command line, in ini files or are added to the effective command line by a module definition.
The XML files instantiate and inject the actual Java objects that comprise the server, connectors and contexts. Because Jetty IoC XML files use properties, most common configuration tasks can be accomplished without editing these XML files and can instead be achieved by editing the property in the corresponding ini files.
The XML files are normally located `$JETTY_HOME/etc/`, but extra or edited XML files may be added to `$JETTY_BASE/etc/`.
XML files in link:#jetty-xml-syntax[Jetty IoC XML format] or Spring IoC format are listed either on the command line, in `ini` files or are added to the effective command line by a module definition.
The XML files instantiate and inject the actual Java objects that comprise the server, connectors and contexts. Because Jetty IoC XML files use properties, most common configuration tasks can be accomplished without editing these XML files and can instead be achieved by editing the property in the corresponding `ini` files.
XML files are normally located in `$JETTY_HOME/etc/`, but extra or edited XML files may be added to `$JETTY_BASE/etc/`.
If XML configuration changes are required, it is best practice to copy the XML file from `$JETTY_HOME/etc/` to `$JETTY_BASE/etc/` before being modified.
==== Other Configuration Files
In addition to the start configuration files described above, the configuration of the server can use the following file:
In addition to the configuration files described above, the configuration of the server can use the following file types:
Context XML files::
Any XML files in link:#jetty-xml-syntax[Jetty IoC XML format] or spring IoC format that is discovered in the webapps directory are used by the deploy module to instantiate and inject HttpContext instances to create a specific context.
Any XML files in link:#jetty-xml-syntax[Jetty IoC XML format] or Spring IoC format that is discovered in the `/webapps` directory are used by the deploy module to instantiate and inject `HttpContext` instances to create a specific context.
These may be standard web applications or bespoke contexts created from special purpose handlers.
`web.xml`::
The http://en.wikipedia.org/wiki/Servlet[Servlet] Specification defines the http://en.wikipedia.org/wiki/Web.xml[`web.xml`] deployment descriptor that defines and configures the filters, servlets and resources a http://en.wikipedia.org/wiki/Web_application[web application] uses.
The Jetty WebAppContext component uses this XML format to:
The Jetty `WebAppContext` component uses this XML format to:
* Set up the default configuration of a web application context.
* Interpret the application-specific configuration supplied with a web application in the `WEB-INF/web.xml` file.
* Interpret descriptor fragments included in the `META-INF` directory of Jar files within `WEB-INF/lib.`
+
Normally the web.xml file for a web application is found in the WEB-INF/web.xml location within the war file/directory or as web.xml fragments with jar files found in WEB-INF/lib.
Jetty also supports multiple web.xml files so that a default descriptor may be applied before WEB-INF/web.xml (typically set to etc/webdefault.xml by the deploy module) and an override descriptor may be applied after WEB-INF/web.xml (typically set by a context XML file see test.xml)
Normally the `web.xml` file for a web application is found in the `WEB-INF/web.xml` location within the war file/directory or as `web.xml` fragments with `.jar` files found in `WEB-INF/lib`.
Jetty also supports multiple `web.xml` files so that a default descriptor may be applied before `WEB-INF/web.xml` (typically set to `etc/webdefault.xml` by the deploy module) and an override descriptor may be applied after `WEB-INF/web.xml` (typically set by a context XML file see `test.xml`)
Property Files::
Standard http://en.wikipedia.org/wiki/Java_properties[Java property files] are also used for Jetty configuration in several ways:
* To parameterize Jetty IoC XML via the use of the Property element.
* To configure the default logging mechanism (StdErrLog). You can also plug in other logging frameworks, and also use property files (for example, log4j).
+
* To parameterize Jetty IoC XML via the use of the `Property` element.
* To configure the default logging mechanism (`StdErrLog`). Other logging frameworks can be utilized and also use property files (for example, `log4j`).
* As a simple database for login usernames and credentials.
==== Jetty IoC XML format
To understand the link:#jetty-xml-syntax[Jetty IoC XML format], consider the following example of an embedded Jetty server instantiated and configured in java:
To understand the link:#jetty-xml-syntax[Jetty IoC XML format], consider the following example of an embedded Jetty server instantiated and configured in Java:
[source,java]
----

View File

@ -21,7 +21,7 @@
Jetty has existed in Maven Central almost since its inception, however under a couple of different coordinates over the years.
When Jetty was based at SourceForge and then The Codehaus it was located under the groupId of `org.mortbay.jetty`.
With Jetty 7 the project moved to the Eclipse foundation and to a new groupId at that time to reflect its new home.
With Jetty 7 the project moved to the Eclipse foundation and to a new `groupId` at that time to reflect its new home.
The top level POM for the Jetty project is located under the following coordinates.
@ -39,7 +39,7 @@ The top level POM for the Jetty project is located under the following coordinat
The changes between versions of Jetty are tracked in a file called VERSIONS.txt, which is under source control and is generated on release.
Those generated files are also uploaded into Maven Central during the release of the top level POM. You can find them as a classifier marked artifact.
http://repo2.maven.org/maven2/org/eclipse/jetty/jetty-project/9.0.0.RC0/jetty-project-9.0.0.RC0-version.txt
http://central.maven.org/maven2/org/eclipse/jetty/jetty-project/
[source,xml]
----

View File

@ -129,7 +129,6 @@ public class ThreadStarvationTest extends HttpServerTestFixture
assertThat(response,containsString("200 OK"));
assertThat(response,containsString("Read Input 10"));
}
}

View File

@ -79,7 +79,8 @@ public interface ExecutionStrategy
*/
Runnable produce();
}
/**
* <p>A factory for {@link ExecutionStrategy}.</p>
*/

View File

@ -43,32 +43,30 @@ import org.eclipse.jetty.util.thread.ThreadPool;
* pressure on producers.
* </p>
*/
public class ExecuteProduceConsume implements ExecutionStrategy, Runnable
public class ExecuteProduceConsume extends ExecutingExecutionStrategy implements ExecutionStrategy, Runnable
{
private static final Logger LOG = Log.getLogger(ExecuteProduceConsume.class);
private final Locker _locker = new Locker();
private final Runnable _runExecute = new RunExecute();
private final Producer _producer;
private final Executor _executor;
private boolean _idle=true;
private boolean _execute;
private boolean _producing;
private boolean _pending;
private final ThreadPool _threadpool;
private final ExecutionStrategy _lowresources;
public ExecuteProduceConsume(Producer producer, Executor executor)
{
this(producer,executor,(executor instanceof ThreadPool)?new ProduceExecuteConsume(producer,executor):null);
super(executor);
this._producer = producer;
_threadpool = (executor instanceof ThreadPool)?((ThreadPool)executor):null;
}
@Deprecated
public ExecuteProduceConsume(Producer producer, Executor executor, ExecutionStrategy lowResourceStrategy)
{
this._producer = producer;
this._executor = executor;
_threadpool = (executor instanceof ThreadPool)?((ThreadPool)executor):null;
_lowresources = _threadpool==null?null:lowResourceStrategy;
this(producer,executor);
}
@Override
@ -100,7 +98,7 @@ public class ExecuteProduceConsume implements ExecutionStrategy, Runnable
}
if (produce)
produceAndRun();
produceConsume();
}
@Override
@ -117,7 +115,7 @@ public class ExecuteProduceConsume implements ExecutionStrategy, Runnable
_execute=true;
}
if (dispatch)
_executor.execute(_runExecute);
execute(_runExecute);
}
@Override
@ -137,28 +135,50 @@ public class ExecuteProduceConsume implements ExecutionStrategy, Runnable
if (produce)
{
// If we are low on resources, then switch to PEC strategy which does not
// suffer as badly from thread starvation
while (_threadpool!=null && _threadpool.isLowOnThreads())
{
LOG.debug("EPC low resources {}",this);
try
{
_lowresources.execute();
}
catch(Throwable e)
{
// just warn if lowresources execute fails and keep producing
LOG.warn(e);
}
}
// If we are low on threads, this could be the last thread, so we must not consume.
// So call produceExecuteConsume instead
if (_threadpool!=null && _threadpool.isLowOnThreads() && !produceExecuteConsume())
return;
// no longer low resources so produceAndRun normally
produceAndRun();
produceConsume();
}
}
private void produceAndRun()
/**
* @return true if we are still producing
*/
private boolean produceExecuteConsume()
{
if (LOG.isDebugEnabled())
LOG.debug("{} Low Resources",this);
while (_threadpool.isLowOnThreads())
{
Runnable task = _producer.produce();
if (LOG.isDebugEnabled())
LOG.debug("{} produced {}", _producer, task);
if (task == null)
{
// No task, so we are now idle
try (Lock locked = _locker.lock())
{
if (LOG.isDebugEnabled())
LOG.debug("{} Idle Low Resources",this);
_producing=false;
_idle=false;
}
return false;
}
// Execute the task.
execute(task);
}
if (LOG.isDebugEnabled())
LOG.debug("{} No longer Low Resources",this);
return true;
}
private void produceConsume()
{
if (LOG.isDebugEnabled())
LOG.debug("{} produce enter",this);
@ -184,6 +204,7 @@ public class ExecuteProduceConsume implements ExecutionStrategy, Runnable
if (task == null)
{
// There is no task.
// Could another one just have been queued with an execute?
if (_execute)
{
_idle=false;
@ -214,30 +235,8 @@ public class ExecuteProduceConsume implements ExecutionStrategy, Runnable
// Spawn a new thread to continue production by running the produce loop.
if (LOG.isDebugEnabled())
LOG.debug("{} dispatch",this);
try
{
_executor.execute(this);
}
catch(RejectedExecutionException e)
{
// If we cannot execute, then discard/reject the task and keep producing
LOG.debug(e);
LOG.warn("RejectedExecution {}",task);
try
{
if (task instanceof Rejectable)
((Rejectable)task).reject();
}
catch (Exception x)
{
e.addSuppressed(x);
LOG.warn(e);
}
finally
{
task=null;
}
}
if (!execute(this))
task=null;
}
// Run the task.
@ -262,6 +261,7 @@ public class ExecuteProduceConsume implements ExecutionStrategy, Runnable
LOG.debug("{} produce exit",this);
}
public Boolean isIdle()
{
try (Lock locked = _locker.lock())

View File

@ -0,0 +1,65 @@
//
// ========================================================================
// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.util.thread.strategy;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.ExecutionStrategy;
public abstract class ExecutingExecutionStrategy implements ExecutionStrategy
{
private static final Logger LOG = Log.getLogger(ExecutingExecutionStrategy.class);
private final Executor _executor;
protected ExecutingExecutionStrategy(Executor executor)
{
_executor=executor;
}
protected boolean execute(Runnable task)
{
try
{
_executor.execute(task);
return true;
}
catch(RejectedExecutionException e)
{
// If we cannot execute, then discard/reject the task and keep producing
LOG.debug(e);
LOG.warn("RejectedExecution {}",task);
try
{
if (task instanceof Rejectable)
((Rejectable)task).reject();
}
catch (Exception x)
{
e.addSuppressed(x);
LOG.warn(e);
}
}
return false;
}
}

View File

@ -19,41 +19,50 @@
package org.eclipse.jetty.util.thread.strategy;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.ExecutionStrategy;
import org.eclipse.jetty.util.thread.Locker;
import org.eclipse.jetty.util.thread.Locker.Lock;
/**
* <p>A strategy where the caller thread iterates over task production, submitting each
* task to an {@link Executor} for execution.</p>
*/
public class ProduceExecuteConsume implements ExecutionStrategy
public class ProduceExecuteConsume extends ExecutingExecutionStrategy implements ExecutionStrategy
{
private static final Logger LOG = Log.getLogger(ProduceExecuteConsume.class);
private final Locker _locker = new Locker();
private final Producer _producer;
private final Executor _executor;
private State _state = State.IDLE;
public ProduceExecuteConsume(Producer producer, Executor executor)
{
super(executor);
this._producer = producer;
this._executor = executor;
}
@Override
public void execute()
{
synchronized (this)
try (Lock locked = _locker.lock())
{
_state = _state == State.IDLE ? State.PRODUCE : State.EXECUTE;
if (_state == State.EXECUTE)
return;
switch(_state)
{
case IDLE:
_state=State.PRODUCE;
break;
case PRODUCE:
case EXECUTE:
_state=State.EXECUTE;
return;
}
}
// Iterate until we are complete.
// Produce until we no task is found.
while (true)
{
// Produce a task.
@ -63,37 +72,25 @@ public class ProduceExecuteConsume implements ExecutionStrategy
if (task == null)
{
synchronized (this)
try (Lock locked = _locker.lock())
{
_state = _state == State.PRODUCE ? State.IDLE : State.PRODUCE;
if (_state == State.PRODUCE)
continue;
return;
switch(_state)
{
case IDLE:
throw new IllegalStateException();
case PRODUCE:
_state=State.IDLE;
return;
case EXECUTE:
_state=State.PRODUCE;
continue;
}
}
}
// Execute the task.
try
{
_executor.execute(task);
}
catch (RejectedExecutionException e)
{
// Discard/reject tasks that cannot be executed
if (task instanceof Rejectable)
{
try
{
((Rejectable)task).reject();
}
catch (Throwable x)
{
e.addSuppressed(x);
LOG.warn(e);
}
}
}
}
execute(task);
}
}
@Override