Merged branch 'jetty-9.4.x' into 'master'.
This commit is contained in:
commit
bee383c894
|
@ -32,7 +32,6 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.SslConnectionFactory;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
|
||||
/**
|
||||
* A Jetty server with multiple connectors.
|
||||
|
|
|
@ -96,20 +96,18 @@ public class ConscryptServerALPNProcessor implements ALPNProcessor.Server
|
|||
@Override
|
||||
public void handshakeSucceeded(Event event)
|
||||
{
|
||||
String protocol = alpnConnection.getProtocol();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("handshakeSucceeded {} {}", alpnConnection, event);
|
||||
if (alpnConnection.getProtocol()==null)
|
||||
{
|
||||
LOG.warn("No ALPN callback! {} {}",alpnConnection, event);
|
||||
LOG.debug("TLS handshake succeeded, protocol={} for {}", protocol, alpnConnection);
|
||||
if (protocol ==null)
|
||||
alpnConnection.unsupported();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeFailed(Event event, Throwable failure)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("handshakeFailed {} {} {}", alpnConnection, event, failure);
|
||||
LOG.debug("TLS handshake failed " + alpnConnection, failure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,20 +78,18 @@ public class JDK9ServerALPNProcessor implements ALPNProcessor.Server, SslHandsha
|
|||
@Override
|
||||
public void handshakeSucceeded(Event event)
|
||||
{
|
||||
String protocol = alpnConnection.getProtocol();
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("handshakeSucceeded {} {}", alpnConnection, event);
|
||||
if (alpnConnection.getProtocol()==null)
|
||||
{
|
||||
LOG.warn("No ALPN callback! {} {}",alpnConnection, event);
|
||||
LOG.debug("TLS handshake succeeded, protocol={} for {}", protocol, alpnConnection);
|
||||
if (protocol ==null)
|
||||
alpnConnection.unsupported();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handshakeFailed(Event event, Throwable failure)
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("handshakeFailed {} {} {}", alpnConnection, event, failure);
|
||||
LOG.debug("TLS handshake failed " + alpnConnection, failure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,9 @@ public class OpenJDK8ClientALPNProcessor implements ALPNProcessor.Client
|
|||
if (JavaVersion.VERSION.getPlatform()!=8)
|
||||
throw new IllegalStateException(this + " not applicable for java "+JavaVersion.VERSION);
|
||||
if (ALPN.class.getClassLoader()!=null)
|
||||
throw new IllegalStateException(this + " must be on JVM boot classpath");
|
||||
throw new IllegalStateException(ALPN.class.getName() + " must be on JVM boot classpath");
|
||||
if (LOG.isDebugEnabled())
|
||||
ALPN.debug = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -206,7 +206,7 @@ public class TestAnnotationConfiguration
|
|||
String dir = MavenTestingUtils.getTargetTestingDir("getFragmentFromJar").getAbsolutePath();
|
||||
File file = new File(dir);
|
||||
file=new File(file.getCanonicalPath());
|
||||
URL url=file.toURL();
|
||||
URL url=file.toURI().toURL();
|
||||
|
||||
Resource jar1 = Resource.newResource(url+"file.jar");
|
||||
|
||||
|
|
|
@ -73,7 +73,6 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
|
|||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
import org.eclipse.jetty.util.thread.ThreadBudget;
|
||||
import org.eclipse.jetty.util.thread.ThreadPool;
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 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.client;
|
||||
|
||||
import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class InsufficientThreadsDetectionTest
|
||||
{
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void testInsufficientThreads() throws Exception
|
||||
{
|
||||
QueuedThreadPool clientThreads = new QueuedThreadPool(1);
|
||||
HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP(1), null);
|
||||
httpClient.setExecutor(clientThreads);
|
||||
httpClient.start();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInsufficientThreadsForMultipleHttpClients() throws Exception
|
||||
{
|
||||
QueuedThreadPool clientThreads = new QueuedThreadPool(3);
|
||||
HttpClient httpClient1 = new HttpClient(new HttpClientTransportOverHTTP(1), null);
|
||||
httpClient1.setExecutor(clientThreads);
|
||||
httpClient1.start();
|
||||
|
||||
try
|
||||
{
|
||||
// Share the same thread pool with another instance.
|
||||
HttpClient httpClient2 = new HttpClient(new HttpClientTransportOverHTTP(1), null);
|
||||
httpClient2.setExecutor(clientThreads);
|
||||
httpClient2.start();
|
||||
Assert.fail();
|
||||
}
|
||||
catch (IllegalStateException expected)
|
||||
{
|
||||
// Expected.
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ import org.eclipse.jetty.client.HttpClientTransport;
|
|||
import org.eclipse.jetty.client.LeakTrackingConnectionPool;
|
||||
import org.eclipse.jetty.fcgi.client.http.HttpClientTransportOverFCGI;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.io.ByteBufferPool;
|
||||
import org.eclipse.jetty.io.LeakTrackingByteBufferPool;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
|
@ -45,7 +46,7 @@ public abstract class AbstractHttpClientServerTest
|
|||
@Rule
|
||||
public final TestTracker tracker = new TestTracker();
|
||||
private LeakTrackingByteBufferPool serverBufferPool;
|
||||
private LeakTrackingByteBufferPool clientBufferPool;
|
||||
protected ByteBufferPool clientBufferPool;
|
||||
private final AtomicLong connectionLeaks = new AtomicLong();
|
||||
protected Server server;
|
||||
protected ServerConnector connector;
|
||||
|
@ -80,7 +81,8 @@ public abstract class AbstractHttpClientServerTest
|
|||
});
|
||||
client = new HttpClient(transport, null);
|
||||
client.setExecutor(executor);
|
||||
clientBufferPool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged());
|
||||
if (clientBufferPool == null)
|
||||
clientBufferPool = new LeakTrackingByteBufferPool(new MappedByteBufferPool.Tagged());
|
||||
client.setByteBufferPool(clientBufferPool);
|
||||
client.start();
|
||||
}
|
||||
|
@ -94,9 +96,13 @@ public abstract class AbstractHttpClientServerTest
|
|||
assertThat("Server BufferPool - leaked releases", serverBufferPool.getLeakedReleases(), Matchers.is(0L));
|
||||
assertThat("Server BufferPool - unreleased", serverBufferPool.getLeakedResources(), Matchers.is(0L));
|
||||
|
||||
assertThat("Client BufferPool - leaked acquires", clientBufferPool.getLeakedAcquires(), Matchers.is(0L));
|
||||
assertThat("Client BufferPool - leaked releases", clientBufferPool.getLeakedReleases(), Matchers.is(0L));
|
||||
assertThat("Client BufferPool - unreleased", clientBufferPool.getLeakedResources(), Matchers.is(0L));
|
||||
if (clientBufferPool instanceof LeakTrackingByteBufferPool)
|
||||
{
|
||||
LeakTrackingByteBufferPool pool = (LeakTrackingByteBufferPool)clientBufferPool;
|
||||
assertThat("Client BufferPool - leaked acquires", pool.getLeakedAcquires(), Matchers.is(0L));
|
||||
assertThat("Client BufferPool - leaked releases", pool.getLeakedReleases(), Matchers.is(0L));
|
||||
assertThat("Client BufferPool - unreleased", pool.getLeakedResources(), Matchers.is(0L));
|
||||
}
|
||||
|
||||
assertThat("Connection Leaks", connectionLeaks.get(), Matchers.is(0L));
|
||||
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.eclipse.jetty.client.util.BytesContentProvider;
|
|||
import org.eclipse.jetty.client.util.DeferredContentProvider;
|
||||
import org.eclipse.jetty.client.util.FutureResponseListener;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.io.MappedByteBufferPool;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.toolchain.test.IO;
|
||||
import org.eclipse.jetty.toolchain.test.annotation.Slow;
|
||||
|
@ -380,6 +381,11 @@ public class HttpClientTest extends AbstractHttpClientServerTest
|
|||
@Test
|
||||
public void testGZIPContentEncoding() throws Exception
|
||||
{
|
||||
// GZIPContentDecoder returns to application pooled
|
||||
// buffers, which is fine, but in this test they will
|
||||
// appear as "leaked", so we use a normal ByteBufferPool.
|
||||
clientBufferPool = new MappedByteBufferPool.Tagged();
|
||||
|
||||
final byte[] data = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
start(new AbstractHandler()
|
||||
{
|
||||
|
|
|
@ -31,7 +31,6 @@ public class MappedByteBufferPool implements ByteBufferPool
|
|||
private final ConcurrentMap<Integer, Bucket> directBuffers = new ConcurrentHashMap<>();
|
||||
private final ConcurrentMap<Integer, Bucket> heapBuffers = new ConcurrentHashMap<>();
|
||||
private final int _factor;
|
||||
private final int _maxQueue;
|
||||
private final Function<Integer, Bucket> _newBucket;
|
||||
|
||||
public MappedByteBufferPool()
|
||||
|
@ -52,8 +51,7 @@ public class MappedByteBufferPool implements ByteBufferPool
|
|||
public MappedByteBufferPool(int factor,int maxQueue,Function<Integer, Bucket> newBucket)
|
||||
{
|
||||
_factor = factor<=0?1024:factor;
|
||||
_maxQueue = maxQueue;
|
||||
_newBucket = newBucket!=null?newBucket:i->new Bucket(this,i*_factor,_maxQueue);
|
||||
_newBucket = newBucket!=null?newBucket:i->new Bucket(this,i*_factor,maxQueue);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -38,8 +38,8 @@ import org.eclipse.jetty.util.log.Log;
|
|||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.thread.ReservedThreadExecutor;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
import org.eclipse.jetty.util.thread.ThreadBudget;
|
||||
import org.eclipse.jetty.util.thread.ThreadPool;
|
||||
import org.eclipse.jetty.util.thread.ThreadPoolBudget;
|
||||
import org.eclipse.jetty.util.thread.strategy.EatWhatYouKill;
|
||||
|
||||
/**
|
||||
|
@ -61,6 +61,7 @@ public abstract class SelectorManager extends ContainerLifeCycle implements Dump
|
|||
private long _connectTimeout = DEFAULT_CONNECT_TIMEOUT;
|
||||
private long _selectorIndex;
|
||||
private int _reservedThreads = -1;
|
||||
private ThreadPoolBudget.Lease _lease;
|
||||
|
||||
private static int defaultSelectors(Executor executor)
|
||||
{
|
||||
|
@ -70,7 +71,6 @@ public abstract class SelectorManager extends ContainerLifeCycle implements Dump
|
|||
int cpus = Runtime.getRuntime().availableProcessors();
|
||||
return Math.max(1,Math.min(cpus/2,threads/16));
|
||||
}
|
||||
|
||||
return Math.max(1,Runtime.getRuntime().availableProcessors()/2);
|
||||
}
|
||||
|
||||
|
@ -297,14 +297,13 @@ public abstract class SelectorManager extends ContainerLifeCycle implements Dump
|
|||
protected void doStart() throws Exception
|
||||
{
|
||||
addBean(new ReservedThreadExecutor(getExecutor(),_reservedThreads,this),true);
|
||||
|
||||
_lease = ThreadPoolBudget.leaseFrom(getExecutor(), this, _selectors.length);
|
||||
for (int i = 0; i < _selectors.length; i++)
|
||||
{
|
||||
ManagedSelector selector = newSelector(i);
|
||||
_selectors[i] = selector;
|
||||
addBean(selector);
|
||||
}
|
||||
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
|
@ -325,6 +324,8 @@ public abstract class SelectorManager extends ContainerLifeCycle implements Dump
|
|||
super.doStop();
|
||||
for (ManagedSelector selector : _selectors)
|
||||
removeBean(selector);
|
||||
if (_lease != null)
|
||||
_lease.close();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,14 +18,6 @@
|
|||
|
||||
package org.eclipse.jetty.io;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
|
@ -34,6 +26,14 @@ import org.eclipse.jetty.util.BufferUtil;
|
|||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
public class MappedByteBufferPoolTest
|
||||
{
|
||||
@Test
|
||||
|
@ -93,8 +93,10 @@ public class MappedByteBufferPoolTest
|
|||
}
|
||||
|
||||
/**
|
||||
* In a scenario where MappedByteBufferPool is being used improperly, such as releasing a buffer that wasn't created/acquired by the MappedByteBufferPool,
|
||||
* an assertion is tested for.
|
||||
* In a scenario where MappedByteBufferPool is being used improperly,
|
||||
* such as releasing a buffer that wasn't created/acquired by the
|
||||
* MappedByteBufferPool, an assertion is tested for.
|
||||
*
|
||||
* @throws Exception test failure
|
||||
*/
|
||||
@Test
|
||||
|
@ -133,8 +135,6 @@ public class MappedByteBufferPoolTest
|
|||
buffer = pool.acquire(1024,false);
|
||||
assertThat(BufferUtil.toDetailString(buffer),containsString("@T00000002"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testMaxQueue() throws Exception
|
||||
|
@ -157,6 +157,5 @@ public class MappedByteBufferPoolTest
|
|||
|
||||
bufferPool.release(buffer3);
|
||||
assertEquals(2, bucket.size());
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,8 +53,7 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
|
|||
import org.eclipse.jetty.util.thread.Locker;
|
||||
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
|
||||
import org.eclipse.jetty.util.thread.Scheduler;
|
||||
import org.eclipse.jetty.util.thread.ThreadBudget;
|
||||
import org.eclipse.jetty.util.thread.ThreadPool;
|
||||
import org.eclipse.jetty.util.thread.ThreadPoolBudget;
|
||||
|
||||
/**
|
||||
* <p>An abstract implementation of {@link Connector} that provides a {@link ConnectionFactory} mechanism
|
||||
|
@ -160,8 +159,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
|
|||
private String _name;
|
||||
private int _acceptorPriorityDelta=-2;
|
||||
private boolean _accepting = true;
|
||||
private ThreadBudget.Lease lease;
|
||||
|
||||
private ThreadPoolBudget.Lease _lease;
|
||||
|
||||
/**
|
||||
* @param server The server this connector will be added to. Must not be null.
|
||||
|
@ -276,7 +274,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
|
|||
throw new IllegalStateException("No protocol factory for SSL next protocol: '" + next + "' in " + this);
|
||||
}
|
||||
|
||||
lease = ThreadBudget.leaseFrom(getExecutor(),this,_acceptors.length);
|
||||
_lease = ThreadPoolBudget.leaseFrom(getExecutor(),this,_acceptors.length);
|
||||
super.doStart();
|
||||
|
||||
_stopping=new CountDownLatch(_acceptors.length);
|
||||
|
@ -312,8 +310,8 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
|
|||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
if (lease!=null)
|
||||
lease.close();
|
||||
if (_lease!=null)
|
||||
_lease.close();
|
||||
|
||||
// Tell the acceptors we are stopping
|
||||
interruptAcceptors();
|
||||
|
|
|
@ -24,7 +24,6 @@ import java.net.InetSocketAddress;
|
|||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
|
@ -66,9 +65,7 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
import org.eclipse.jetty.util.thread.Locker;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.eclipse.jetty.util.thread.ShutdownThread;
|
||||
import org.eclipse.jetty.util.thread.ThreadBudget;
|
||||
import org.eclipse.jetty.util.thread.ThreadPool;
|
||||
import org.eclipse.jetty.util.thread.ThreadPool.SizedThreadPool;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Jetty HTTP Servlet Server.
|
||||
|
|
|
@ -21,8 +21,8 @@ package org.eclipse.jetty.server;
|
|||
import org.eclipse.jetty.toolchain.test.AdvancedRunner;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||
import org.eclipse.jetty.util.thread.ThreadBudget;
|
||||
import org.eclipse.jetty.util.thread.ThreadPool;
|
||||
import org.eclipse.jetty.util.thread.ThreadPoolBudget;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
@ -61,7 +61,7 @@ public class InsufficientThreadsDetectionTest
|
|||
}
|
||||
catch(IllegalStateException e)
|
||||
{
|
||||
Log.getLogger(ThreadBudget.class).warn(e.toString());
|
||||
Log.getLogger(ThreadPoolBudget.class).warn(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,8 +82,6 @@ public class InsufficientThreadsDetectionTest
|
|||
_server.start();
|
||||
}
|
||||
|
||||
// Github issue #586
|
||||
|
||||
@Test
|
||||
public void testCaseForMultipleConnectors() throws Exception
|
||||
{
|
||||
|
@ -95,22 +93,21 @@ public class InsufficientThreadsDetectionTest
|
|||
// first connector consumes 3 threads from server pool
|
||||
_server.addConnector(new ServerConnector(_server, null, null, null, 1, 1, new HttpConnectionFactory()));
|
||||
|
||||
// second connect also require 4 threads but uses own executor, so its threads should not be counted
|
||||
// second connect also require 3 threads but uses own executor, so its threads should not be counted
|
||||
final QueuedThreadPool connectorPool = new QueuedThreadPool(4, 4);
|
||||
_server.addConnector(new ServerConnector(_server, connectorPool, null, null, 1, 1, new HttpConnectionFactory()));
|
||||
|
||||
// first connector consumes 3 threads from server pool
|
||||
// third connector consumes 3 threads from server pool
|
||||
_server.addConnector(new ServerConnector(_server, null, null, null, 1, 1, new HttpConnectionFactory()));
|
||||
|
||||
// should not throw exception because limit was not overflown
|
||||
// should throw exception because limit was overflown
|
||||
_server.start();
|
||||
|
||||
Assert.fail();
|
||||
}
|
||||
catch(IllegalStateException e)
|
||||
{
|
||||
Log.getLogger(ThreadBudget.class).warn(e.toString());
|
||||
Log.getLogger(ThreadPoolBudget.class).warn(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,11 +18,7 @@
|
|||
|
||||
package org.eclipse.jetty.util.component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* A Container
|
||||
|
|
|
@ -65,7 +65,7 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo
|
|||
private boolean _daemon = false;
|
||||
private boolean _detailedDump = false;
|
||||
private int _lowThreadsThreshold = 1;
|
||||
private ThreadBudget _budget;
|
||||
private ThreadPoolBudget _budget;
|
||||
|
||||
public QueuedThreadPool()
|
||||
{
|
||||
|
@ -106,23 +106,20 @@ public class QueuedThreadPool extends AbstractLifeCycle implements SizedThreadPo
|
|||
}
|
||||
_jobs=queue;
|
||||
_threadGroup=threadGroup;
|
||||
_budget=new ThreadBudget(this);
|
||||
_budget=new ThreadPoolBudget(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThreadBudget getThreadBudget()
|
||||
public ThreadPoolBudget getThreadPoolBudget()
|
||||
{
|
||||
return _budget;
|
||||
}
|
||||
|
||||
public void setThreadBudget(ThreadBudget budget)
|
||||
public void setThreadPoolBudget(ThreadPoolBudget budget)
|
||||
{
|
||||
if (budget!=null && budget.getSizedThreadPool()!=this)
|
||||
throw new IllegalArgumentException();
|
||||
synchronized (this)
|
||||
{
|
||||
_budget = budget;
|
||||
}
|
||||
_budget = budget;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -64,7 +64,7 @@ public class ReservedThreadExecutor extends AbstractLifeCycle implements Executo
|
|||
private final AtomicInteger _size = new AtomicInteger();
|
||||
private final AtomicInteger _pending = new AtomicInteger();
|
||||
|
||||
private ThreadBudget.Lease _lease;
|
||||
private ThreadPoolBudget.Lease _lease;
|
||||
private Object _owner;
|
||||
private long _idleTime = 1L;
|
||||
private TimeUnit _idleTimeUnit = TimeUnit.MINUTES;
|
||||
|
@ -168,7 +168,7 @@ public class ReservedThreadExecutor extends AbstractLifeCycle implements Executo
|
|||
@Override
|
||||
public void doStart() throws Exception
|
||||
{
|
||||
_lease = ThreadBudget.leaseFrom(getExecutor(),this,_capacity);
|
||||
_lease = ThreadPoolBudget.leaseFrom(getExecutor(),this,_capacity);
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
|
|
|
@ -71,8 +71,7 @@ public interface ThreadPool extends Executor
|
|||
int getMaxThreads();
|
||||
void setMinThreads(int threads);
|
||||
void setMaxThreads(int threads);
|
||||
|
||||
default ThreadBudget getThreadBudget()
|
||||
default ThreadPoolBudget getThreadPoolBudget()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -31,11 +31,11 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
/**
|
||||
* <p>A budget of required thread usage, used to warn or error for insufficient configured threads.</p>
|
||||
*
|
||||
* @see ThreadPool.SizedThreadPool#getThreadBudget()
|
||||
* @see ThreadPool.SizedThreadPool#getThreadPoolBudget()
|
||||
*/
|
||||
public class ThreadBudget
|
||||
public class ThreadPoolBudget
|
||||
{
|
||||
static final Logger LOG = Log.getLogger(ThreadBudget.class);
|
||||
static final Logger LOG = Log.getLogger(ThreadPoolBudget.class);
|
||||
|
||||
public interface Lease extends Closeable
|
||||
{
|
||||
|
@ -92,10 +92,10 @@ public class ThreadBudget
|
|||
final int warnAt;
|
||||
|
||||
/**
|
||||
* Construct a bedget for a SizedThreadPool, with the warning level set by heuristic.
|
||||
* Construct a budget for a SizedThreadPool, with the warning level set by heuristic.
|
||||
* @param pool The pool to budget thread allocation for.
|
||||
*/
|
||||
public ThreadBudget(ThreadPool.SizedThreadPool pool)
|
||||
public ThreadPoolBudget(ThreadPool.SizedThreadPool pool)
|
||||
{
|
||||
this(pool,Runtime.getRuntime().availableProcessors());
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ public class ThreadBudget
|
|||
* @param pool The pool to budget thread allocation for.
|
||||
* @param warnAt The level of free threads at which a warning is generated.
|
||||
*/
|
||||
public ThreadBudget(ThreadPool.SizedThreadPool pool, int warnAt)
|
||||
public ThreadPoolBudget(ThreadPool.SizedThreadPool pool, int warnAt)
|
||||
{
|
||||
this.pool = pool;
|
||||
this.warnAt = warnAt;
|
||||
|
@ -139,20 +139,20 @@ public class ThreadBudget
|
|||
int required = allocations.stream()
|
||||
.mapToInt(Lease::getThreads)
|
||||
.sum();
|
||||
|
||||
int maximum = pool.getMaxThreads();
|
||||
int actual = maximum - required;
|
||||
|
||||
if (required>=maximum)
|
||||
if (actual <= 0)
|
||||
{
|
||||
infoOnLeases();
|
||||
throw new IllegalStateException(String.format("Insuffient configured threads: required=%d < max=%d for %s", required, maximum, pool));
|
||||
throw new IllegalStateException(String.format("Insufficient configured threads: required=%d < max=%d for %s", required, maximum, pool));
|
||||
}
|
||||
|
||||
if ((maximum-required) < warnAt)
|
||||
if (actual < warnAt)
|
||||
{
|
||||
infoOnLeases();
|
||||
if (warned.compareAndSet(false,true))
|
||||
LOG.warn("Low configured threads: ( max={} - required={} ) < warnAt={} for {}", maximum, required, warnAt, pool);
|
||||
LOG.warn("Low configured threads: (max={} - required={})={} < warnAt={} for {}", maximum, required, actual, warnAt, pool);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,7 @@ public class ThreadBudget
|
|||
{
|
||||
if (executor instanceof ThreadPool.SizedThreadPool)
|
||||
{
|
||||
ThreadBudget budget = ((ThreadPool.SizedThreadPool)executor).getThreadBudget();
|
||||
ThreadPoolBudget budget = ((ThreadPool.SizedThreadPool)executor).getThreadPoolBudget();
|
||||
if (budget!=null)
|
||||
return budget.leaseTo(leasee,threads);
|
||||
}
|
2
pom.xml
2
pom.xml
|
@ -417,7 +417,7 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.20</version>
|
||||
<version>2.20.1</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
|
|
@ -38,5 +38,6 @@
|
|||
<module>test-servlet-spec</module>
|
||||
<module>test-jaas-webapp</module>
|
||||
<module>test-jndi-webapp</module>
|
||||
<module>test-http2-webapp</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>test-webapps-parent</artifactId>
|
||||
<version>9.4.8-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>test-http2-webapp</artifactId>
|
||||
<name>Test :: Jetty HTTP2 Webapp</name>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<properties>
|
||||
<bundle-symbolic-name>${project.groupId}.http2</bundle-symbolic-name>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>unpack-webapp</id>
|
||||
<phase>pre-integration-test</phase>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>${project.artifactId}</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>war</type>
|
||||
<overWrite>false</overWrite>
|
||||
<outputDirectory>${project.build.directory}/webapp</outputDirectory>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>integration-test</goal>
|
||||
<goal>verify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>jdk8</id>
|
||||
<activation>
|
||||
<jdk>[1.8,1.9)</jdk>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-alpn-boot</id>
|
||||
<phase>pre-integration-test</phase>
|
||||
<goals>
|
||||
<goal>copy</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.mortbay.jetty.alpn</groupId>
|
||||
<artifactId>alpn-boot</artifactId>
|
||||
<version>${alpn.version}</version>
|
||||
<type>jar</type>
|
||||
<overWrite>false</overWrite>
|
||||
<outputDirectory>${project.build.directory}/alpn</outputDirectory>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>-Xbootclasspath/p:${project.build.directory}/alpn/alpn-boot-${alpn.version}.jar</argLine>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-openjdk8-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty.alpn</groupId>
|
||||
<artifactId>alpn-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-openjdk8-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>jdk9</id>
|
||||
<activation>
|
||||
<jdk>[1.9,)</jdk>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-java-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-alpn-java-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-client</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.http2</groupId>
|
||||
<artifactId>http2-server</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,138 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 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.test.webapp;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.http.MetaData;
|
||||
import org.eclipse.jetty.http2.api.Session;
|
||||
import org.eclipse.jetty.http2.api.Stream;
|
||||
import org.eclipse.jetty.http2.client.HTTP2Client;
|
||||
import org.eclipse.jetty.http2.frames.DataFrame;
|
||||
import org.eclipse.jetty.http2.frames.HeadersFrame;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.Promise;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
||||
public class HTTP1Servlet extends HttpServlet
|
||||
{
|
||||
private SslContextFactory sslContextFactory;
|
||||
private HTTP2Client http2Client;
|
||||
|
||||
@Override
|
||||
public void init() throws ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
sslContextFactory = new SslContextFactory(true);
|
||||
http2Client = new HTTP2Client();
|
||||
http2Client.addBean(sslContextFactory);
|
||||
http2Client.start();
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
throw new ServletException(x);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
try
|
||||
{
|
||||
http2Client.stop();
|
||||
}
|
||||
catch (Exception x)
|
||||
{
|
||||
x.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
String host = "localhost";
|
||||
int port = request.getServerPort();
|
||||
String contextPath = request.getContextPath();
|
||||
ServletOutputStream output = response.getOutputStream();
|
||||
AsyncContext asyncContext = request.startAsync();
|
||||
http2Client.connect(sslContextFactory, new InetSocketAddress(host, port), new Session.Listener.Adapter(), new Promise<Session>()
|
||||
{
|
||||
@Override
|
||||
public void succeeded(Session session)
|
||||
{
|
||||
HttpURI uri = new HttpURI(request.getScheme(), host, port, contextPath + "/h2");
|
||||
MetaData.Request metaData = new MetaData.Request(HttpMethod.GET.asString(), uri, HttpVersion.HTTP_2, new HttpFields());
|
||||
HeadersFrame frame = new HeadersFrame(metaData, null, true);
|
||||
session.newStream(frame, new Promise.Adapter<Stream>()
|
||||
{
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
{
|
||||
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500);
|
||||
response.setHeader("X-Failure", "stream");
|
||||
asyncContext.complete();
|
||||
}
|
||||
}, new Stream.Listener.Adapter()
|
||||
{
|
||||
@Override
|
||||
public void onData(Stream stream, DataFrame frame, Callback callback)
|
||||
{
|
||||
try
|
||||
{
|
||||
ByteBuffer buffer = frame.getData();
|
||||
byte[] bytes = new byte[buffer.remaining()];
|
||||
buffer.get(bytes);
|
||||
output.write(bytes);
|
||||
callback.succeeded();
|
||||
if (frame.isEndStream())
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
asyncContext.complete();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void failed(Throwable x)
|
||||
{
|
||||
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500);
|
||||
response.setHeader("X-Failure", "session");
|
||||
asyncContext.complete();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 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.test.webapp;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class HTTP2Servlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||
{
|
||||
response.getOutputStream().print("ok");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||
version="3.1">
|
||||
|
||||
<servlet>
|
||||
<servlet-name>h1</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.test.webapp.HTTP1Servlet</servlet-class>
|
||||
<async-supported>true</async-supported>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>h1</servlet-name>
|
||||
<url-pattern>/h1</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>h2</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.test.webapp.HTTP2Servlet</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>h2</servlet-name>
|
||||
<url-pattern>/h2</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
</web-app>
|
||||
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2017 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.test.webapp;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
|
||||
import org.eclipse.jetty.client.HttpClient;
|
||||
import org.eclipse.jetty.client.api.ContentResponse;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.http2.HTTP2Cipher;
|
||||
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.SecureRequestCustomizer;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.server.SslConnectionFactory;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class HTTP2FromWebAppIT
|
||||
{
|
||||
@Test
|
||||
public void testHTTP2FromWebApp() throws Exception
|
||||
{
|
||||
Server server = new Server();
|
||||
|
||||
SslContextFactory serverTLS = new SslContextFactory();
|
||||
serverTLS.setKeyStorePath("src/test/resources/keystore.jks");
|
||||
serverTLS.setKeyStorePassword("storepwd");
|
||||
serverTLS.setCipherComparator(new HTTP2Cipher.CipherComparator());
|
||||
|
||||
HttpConfiguration httpsConfig = new HttpConfiguration();
|
||||
httpsConfig.addCustomizer(new SecureRequestCustomizer());
|
||||
|
||||
HttpConnectionFactory h1 = new HttpConnectionFactory(httpsConfig);
|
||||
ALPNServerConnectionFactory alpn = new ALPNServerConnectionFactory();
|
||||
alpn.setDefaultProtocol(h1.getProtocol());
|
||||
SslConnectionFactory ssl = new SslConnectionFactory(serverTLS, alpn.getProtocol());
|
||||
HTTP2ServerConnectionFactory h2 = new HTTP2ServerConnectionFactory(httpsConfig);
|
||||
|
||||
ServerConnector connector = new ServerConnector(server, ssl, alpn, h2, h1);
|
||||
server.addConnector(connector);
|
||||
|
||||
String contextPath = "/http2_from_webapp";
|
||||
WebAppContext context = new WebAppContext("target/webapp", contextPath);
|
||||
server.setHandler(context);
|
||||
|
||||
server.start();
|
||||
|
||||
try
|
||||
{
|
||||
SslContextFactory clientTLS = new SslContextFactory(true);
|
||||
HttpClient client = new HttpClient(clientTLS);
|
||||
client.start();
|
||||
|
||||
try
|
||||
{
|
||||
ContentResponse response = client.newRequest("localhost", connector.getLocalPort())
|
||||
.scheme(HttpScheme.HTTPS.asString())
|
||||
.path(contextPath + "/h1")
|
||||
.timeout(5, TimeUnit.SECONDS)
|
||||
.send();
|
||||
|
||||
Assert.assertEquals("ok", response.getContentAsString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.stop();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
|
||||
org.eclipse.jetty.LEVEL=INFO
|
||||
#org.eclipse.jetty.alpn.LEVEL=DEBUG
|
Binary file not shown.
Loading…
Reference in New Issue