Fixes #4258 - RateControl should be per-connection.
Introduced RateControl.Factory to create instances of RateControl for each connection. Modified relevant XML files and added distribution test for h2. Signed-off-by: Simone Bordet <simone.bordet@gmail.com>
This commit is contained in:
parent
e09444eeb5
commit
f8449868e6
|
@ -36,4 +36,18 @@ public interface RateControl
|
|||
* @return true IFF the rate is within limits
|
||||
*/
|
||||
public boolean onEvent(Object event);
|
||||
|
||||
/**
|
||||
* Factory to create RateControl instances.
|
||||
*/
|
||||
public interface Factory
|
||||
{
|
||||
/**
|
||||
* @return a new RateControl instance.
|
||||
*/
|
||||
public default RateControl newRateControl()
|
||||
{
|
||||
return NO_RATE_CONTROL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,4 +67,20 @@ public class WindowRateControl implements RateControl
|
|||
events.add(now + window);
|
||||
return size.incrementAndGet() <= maxEvents;
|
||||
}
|
||||
|
||||
public static class Factory implements RateControl.Factory
|
||||
{
|
||||
private final int maxEventRate;
|
||||
|
||||
public Factory(int maxEventRate)
|
||||
{
|
||||
this.maxEventRate = maxEventRate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RateControl newRateControl()
|
||||
{
|
||||
return WindowRateControl.fromEventsPerSecond(maxEventRate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<!-- ============================================================= --><!-- Configure an HTTP2 on the ssl connector. --><!-- ============================================================= -->
|
||||
<Configure id="sslConnector" class="org.eclipse.jetty.server.ServerConnector">
|
||||
<Call name="addConnectionFactory">
|
||||
<Arg>
|
||||
|
@ -10,10 +10,10 @@
|
|||
<Set name="initialStreamRecvWindow"><Property name="jetty.http2.initialStreamRecvWindow" default="524288"/></Set>
|
||||
<Set name="initialSessionRecvWindow"><Property name="jetty.http2.initialSessionRecvWindow" default="1048576"/></Set>
|
||||
<Set name="maxSettingsKeys"><Property name="jetty.http2.maxSettingsKeys" default="64"/></Set>
|
||||
<Set name="rateControl">
|
||||
<Call class="org.eclipse.jetty.http2.parser.WindowRateControl" name="fromEventsPerSecond">
|
||||
<Set name="rateControlFactory">
|
||||
<New class="org.eclipse.jetty.http2.parser.WindowRateControl$Factory">
|
||||
<Arg type="int"><Property name="jetty.http2.rateControl.maxEventsPerSecond" default="20"/></Arg>
|
||||
</Call>
|
||||
</New>
|
||||
</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
|
||||
|
||||
<!-- ============================================================= --><!-- Configure an HTTP2 on the ssl connector. --><!-- ============================================================= -->
|
||||
<Configure id="httpConnector" class="org.eclipse.jetty.server.ServerConnector">
|
||||
<Call name="addConnectionFactory">
|
||||
<Arg>
|
||||
|
@ -9,10 +9,10 @@
|
|||
<Set name="maxConcurrentStreams"><Property name="jetty.http2c.maxConcurrentStreams" deprecated="http2.maxConcurrentStreams" default="1024"/></Set>
|
||||
<Set name="initialStreamRecvWindow"><Property name="jetty.http2c.initialStreamRecvWindow" default="65535"/></Set>
|
||||
<Set name="maxSettingsKeys"><Property name="jetty.http2.maxSettingsKeys" default="64"/></Set>
|
||||
<Set name="rateControl">
|
||||
<Call class="org.eclipse.jetty.http2.parser.WindowRateControl" name="fromEventsPerSecond">
|
||||
<Set name="rateControlFactory">
|
||||
<New class="org.eclipse.jetty.http2.parser.WindowRateControl$Factory">
|
||||
<Arg type="int"><Property name="jetty.http2.rateControl.maxEventsPerSecond" default="20"/></Arg>
|
||||
</Call>
|
||||
</New>
|
||||
</Set>
|
||||
</New>
|
||||
</Arg>
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
package org.eclipse.jetty.http2.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
@ -61,7 +60,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
private int maxHeaderBlockFragment = 0;
|
||||
private int maxFrameLength = Frame.DEFAULT_MAX_LENGTH;
|
||||
private int maxSettingsKeys = SettingsFrame.DEFAULT_MAX_KEYS;
|
||||
private RateControl rateControl = new WindowRateControl(20, Duration.ofSeconds(1));
|
||||
private RateControl.Factory rateControlFactory = new WindowRateControl.Factory(20);
|
||||
private FlowControlStrategy.Factory flowControlStrategyFactory = () -> new BufferingFlowControlStrategy(0.5F);
|
||||
private long streamIdleTimeout;
|
||||
|
||||
|
@ -182,14 +181,43 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
this.maxSettingsKeys = maxSettingsKeys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return null
|
||||
* @deprecated use {@link #getRateControlFactory()} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public RateControl getRateControl()
|
||||
{
|
||||
return rateControl;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rateControl ignored
|
||||
* @throws UnsupportedOperationException when invoked
|
||||
* @deprecated use {@link #setRateControlFactory(RateControl.Factory)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public void setRateControl(RateControl rateControl)
|
||||
{
|
||||
this.rateControl = rateControl;
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the factory that creates RateControl objects
|
||||
*/
|
||||
public RateControl.Factory getRateControlFactory()
|
||||
{
|
||||
return rateControlFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Sets the factory that creates a per-connection RateControl object.</p>
|
||||
*
|
||||
* @param rateControlFactory the factory that creates RateControl objects
|
||||
*/
|
||||
public void setRateControlFactory(RateControl.Factory rateControlFactory)
|
||||
{
|
||||
this.rateControlFactory = Objects.requireNonNull(rateControlFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -251,7 +279,7 @@ public abstract class AbstractHTTP2ServerConnectionFactory extends AbstractConne
|
|||
session.setInitialSessionRecvWindow(getInitialSessionRecvWindow());
|
||||
session.setWriteThreshold(getHttpConfiguration().getOutputBufferSize());
|
||||
|
||||
ServerParser parser = newServerParser(connector, session, getRateControl());
|
||||
ServerParser parser = newServerParser(connector, session, getRateControlFactory().newRateControl());
|
||||
parser.setMaxFrameLength(getMaxFrameLength());
|
||||
parser.setMaxSettingsKeys(getMaxSettingsKeys());
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.eclipse.jetty.unixsocket.UnixSocketConnector;
|
|||
import org.eclipse.jetty.unixsocket.client.HttpClientTransportOverUnixSockets;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.condition.DisabledOnJre;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
|
@ -155,6 +156,18 @@ public class DistributionTests extends AbstractDistributionTest
|
|||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_8)
|
||||
public void testSimpleWebAppWithJSPOverH2C() throws Exception
|
||||
{
|
||||
testSimpleWebAppWithJSPOverHTTP2(false);
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisabledOnJre(JRE.JAVA_8)
|
||||
public void testSimpleWebAppWithJSPOverH2() throws Exception
|
||||
{
|
||||
testSimpleWebAppWithJSPOverHTTP2(true);
|
||||
}
|
||||
|
||||
private void testSimpleWebAppWithJSPOverHTTP2(boolean ssl) throws Exception
|
||||
{
|
||||
String jettyVersion = System.getProperty("jettyVersion");
|
||||
DistributionTester distribution = DistributionTester.Builder.newInstance()
|
||||
|
@ -164,7 +177,7 @@ public class DistributionTests extends AbstractDistributionTest
|
|||
|
||||
String[] args1 = {
|
||||
"--create-startd",
|
||||
"--add-to-start=http2c,jsp,deploy"
|
||||
"--add-to-start=jsp,deploy," + (ssl ? "http2" : "http2c")
|
||||
};
|
||||
try (DistributionTester.Run run1 = distribution.start(args1))
|
||||
{
|
||||
|
@ -175,13 +188,14 @@ public class DistributionTests extends AbstractDistributionTest
|
|||
distribution.installWarFile(war, "test");
|
||||
|
||||
int port = distribution.freePort();
|
||||
try (DistributionTester.Run run2 = distribution.start("jetty.http.port=" + port))
|
||||
String portProp = ssl ? "jetty.ssl.port" : "jetty.http.port";
|
||||
try (DistributionTester.Run run2 = distribution.start(portProp + "=" + port))
|
||||
{
|
||||
assertTrue(run2.awaitConsoleLogsFor("Started @", 10, TimeUnit.SECONDS));
|
||||
|
||||
HTTP2Client h2Client = new HTTP2Client();
|
||||
startHttpClient(() -> new HttpClient(new HttpClientTransportOverHTTP2(h2Client), null));
|
||||
ContentResponse response = client.GET("http://localhost:" + port + "/test/index.jsp");
|
||||
startHttpClient(() -> new HttpClient(new HttpClientTransportOverHTTP2(h2Client), new SslContextFactory.Client(true)));
|
||||
ContentResponse response = client.GET((ssl ? "https" : "http") + "://localhost:" + port + "/test/index.jsp");
|
||||
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
assertThat(response.getContentAsString(), containsString("Hello"));
|
||||
assertThat(response.getContentAsString(), not(containsString("<%")));
|
||||
|
|
Loading…
Reference in New Issue