Add TripleConfig to ProtocolConfig as nest configuration (#14077)

* Add TripleConfig to ProtocolConfig as nest configuration

* Fix compile issue

* Use default protocol config

* Format code

* Handle the situation where ProtocolConfig is not set

* Follow the old rules and fix some sonar issues

* Add checkDefault method

* Refresh when uninitialized

* Remove needRefresh

---------

Co-authored-by: earthchen <earthchen1996@gmail.com>
This commit is contained in:
TomlongTK 2024-05-23 11:15:06 +08:00 committed by GitHub
parent 1f6d441de6
commit b5bb04496c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 886 additions and 252 deletions

View File

@ -19,6 +19,8 @@ package org.apache.dubbo.config;
import org.apache.dubbo.common.serialization.PreferSerializationProvider;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.nested.TripleConfig;
import org.apache.dubbo.config.support.Nested;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.model.ApplicationModel;
@ -236,6 +238,9 @@ public class ProtocolConfig extends AbstractConfig {
*/
private String jsonCheckLevel;
@Nested
private TripleConfig triple;
public ProtocolConfig() {}
public ProtocolConfig(ApplicationModel applicationModel) {
@ -277,6 +282,11 @@ public class ProtocolConfig extends AbstractConfig {
.getBean(PreferSerializationProvider.class)
.getPreferSerialization();
}
if (triple == null) {
triple = new TripleConfig();
}
triple.checkDefault();
}
@Parameter(excluded = true)
@ -621,6 +631,14 @@ public class ProtocolConfig extends AbstractConfig {
this.extProtocol = extProtocol;
}
public TripleConfig getTriple() {
return triple;
}
public void setTriple(TripleConfig triple) {
this.triple = triple;
}
public void mergeProtocol(ProtocolConfig sourceConfig) {
if (sourceConfig == null) {
return;

View File

@ -1,118 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config;
import java.io.Serializable;
/**
* Configuration for triple protocol.
*/
public class TripleConfig implements Serializable {
private static final long serialVersionUID = -3682252713701362155L;
/**
* The header table size.
*/
private String headerTableSize;
/**
* Whether to enable push, default is false.
*/
private Boolean enablePush;
/**
* Maximum concurrent streams.
*/
private String maxConcurrentStreams;
/**
* Initial window size.
*/
private String initialWindowSize;
/**
* Maximum frame size.
*/
private String maxFrameSize;
/**
* Maximum header list size.
*/
private String maxHeaderListSize;
/**
* Whether to pass through standard HTTP headers, default is false.
*/
private Boolean passThroughStandardHttpHeaders;
public String getHeaderTableSize() {
return headerTableSize;
}
public void setHeaderTableSize(String headerTableSize) {
this.headerTableSize = headerTableSize;
}
public Boolean getEnablePush() {
return enablePush;
}
public void setEnablePush(Boolean enablePush) {
this.enablePush = enablePush;
}
public String getMaxConcurrentStreams() {
return maxConcurrentStreams;
}
public void setMaxConcurrentStreams(String maxConcurrentStreams) {
this.maxConcurrentStreams = maxConcurrentStreams;
}
public String getInitialWindowSize() {
return initialWindowSize;
}
public void setInitialWindowSize(String initialWindowSize) {
this.initialWindowSize = initialWindowSize;
}
public String getMaxFrameSize() {
return maxFrameSize;
}
public void setMaxFrameSize(String maxFrameSize) {
this.maxFrameSize = maxFrameSize;
}
public String getMaxHeaderListSize() {
return maxHeaderListSize;
}
public void setMaxHeaderListSize(String maxHeaderListSize) {
this.maxHeaderListSize = maxHeaderListSize;
}
public Boolean getPassThroughStandardHttpHeaders() {
return passThroughStandardHttpHeaders;
}
public void setPassThroughStandardHttpHeaders(Boolean passThroughStandardHttpHeaders) {
this.passThroughStandardHttpHeaders = passThroughStandardHttpHeaders;
}
}

View File

@ -419,7 +419,7 @@ public abstract class AbstractConfigManager extends LifecycleAdapter {
List<C> list = configsMap.values().stream()
.filter(c -> TRUE.equals(AbstractConfigManager.isDefaultConfig(c)))
.collect(Collectors.toList());
if (list.size() > 0) {
if (!list.isEmpty()) {
return list;
}
@ -635,10 +635,7 @@ public abstract class AbstractConfigManager extends LifecycleAdapter {
* @return
*/
protected <T extends AbstractConfig> boolean isNeedValidation(T config) {
if (config instanceof MetadataReportConfig) {
return false;
}
return true;
return !(config instanceof MetadataReportConfig);
}
private ConfigValidator getConfigValidator() {
@ -656,14 +653,11 @@ public abstract class AbstractConfigManager extends LifecycleAdapter {
* @return
*/
protected <T extends AbstractConfig> boolean isRequired(Class<T> clazz) {
if (clazz == RegistryConfig.class
|| clazz == MetadataReportConfig.class
|| clazz == MonitorConfig.class
|| clazz == MetricsConfig.class
|| clazz == TracingConfig.class) {
return false;
}
return true;
return clazz != RegistryConfig.class
&& clazz != MetadataReportConfig.class
&& clazz != MonitorConfig.class
&& clazz != MetricsConfig.class
&& clazz != TracingConfig.class;
}
private <T extends AbstractConfig> boolean shouldAddDefaultConfig(Class<T> clazz) {

View File

@ -197,6 +197,21 @@ public class ConfigManager extends AbstractConfigManager implements ApplicationE
return getConfig(ProtocolConfig.class, idOrName);
}
public ProtocolConfig getOrAddProtocol(String idOrName) {
Optional<ProtocolConfig> protocol = getProtocol(idOrName);
if (protocol.isPresent()) {
return protocol.get();
}
ProtocolConfig protocolConfig = new ProtocolConfig(idOrName);
addProtocol(protocolConfig);
// addProtocol triggers refresh when other protocols exist in the ConfigManager.
// So refresh is only done when ProtocolConfig is not refreshed.
if (!protocolConfig.isRefreshed()) {
protocolConfig.refresh();
}
return protocolConfig;
}
public List<ProtocolConfig> getDefaultProtocols() {
return getDefaultConfigs(ProtocolConfig.class);
}

View File

@ -0,0 +1,237 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.nested;
import java.io.Serializable;
/**
* Configuration for triple protocol.
*/
public class TripleConfig implements Serializable {
private static final long serialVersionUID = -3682252713701362155L;
/**
* Maximum allowed size for HTTP1 request bodies.
* Limits the size of request to prevent excessively large request.
* <p>The default value is 8MiB.
*/
private Integer maxBodySize;
/**
* Maximum allowed size for HTTP1 response bodies.
* Limits the size of responses to prevent excessively large response.
* <p>The default value is 8MiB.
*/
private Integer maxResponseBodySize;
/**
* Set the maximum chunk size.
* HTTP requests and responses can be quite large, in which case it's better to process the data as a stream of
* chunks.
* This sets the limit, in bytes, at which Netty will send a chunk down the pipeline.
* <p>The default value is 8MiB.
*/
private Integer maxChunkSize;
/**
* Set the maximum line length of header lines.
* This limits how much memory Netty will use when parsing HTTP header key-value pairs.
* You would typically set this to the same value as {@link #setMaxInitialLineLength(Integer)}.
* <p>The default value is 8KiB.
*/
private Integer maxHeaderSize;
/**
* Set the maximum length of the first line of the HTTP header.
* This limits how much memory Netty will use when parsed the initial HTTP header line.
* You would typically set this to the same value as {@link #setMaxHeaderSize(Integer)}.
* <p>The default value is 4096.
*/
private Integer maxInitialLineLength;
/**
* Set the initial size of the temporary buffer used when parsing the lines of the HTTP headers.
* <p>The default value is 16384 octets.
*/
private Integer initialBufferSize;
/**
* The header table size.
*/
private Integer headerTableSize;
/**
* Whether to enable push, default is false.
*/
private Boolean enablePush;
/**
* Maximum concurrent streams.
*/
private Integer maxConcurrentStreams;
/**
* Initial window size.
*/
private Integer initialWindowSize;
/**
* Maximum frame size.
*/
private Integer maxFrameSize;
/**
* Maximum header list size.
*/
private Integer maxHeaderListSize;
public Integer getMaxBodySize() {
return maxBodySize;
}
public void setMaxBodySize(Integer maxBodySize) {
this.maxBodySize = maxBodySize;
}
public Integer getMaxResponseBodySize() {
return maxResponseBodySize;
}
public void setMaxResponseBodySize(Integer maxResponseBodySize) {
this.maxResponseBodySize = maxResponseBodySize;
}
public Integer getMaxChunkSize() {
return maxChunkSize;
}
public void setMaxChunkSize(Integer maxChunkSize) {
this.maxChunkSize = maxChunkSize;
}
public Integer getMaxHeaderSize() {
return maxHeaderSize;
}
public void setMaxHeaderSize(Integer maxHeaderSize) {
this.maxHeaderSize = maxHeaderSize;
}
public Integer getMaxInitialLineLength() {
return maxInitialLineLength;
}
public void setMaxInitialLineLength(Integer maxInitialLineLength) {
this.maxInitialLineLength = maxInitialLineLength;
}
public Integer getInitialBufferSize() {
return initialBufferSize;
}
public void setInitialBufferSize(Integer initialBufferSize) {
this.initialBufferSize = initialBufferSize;
}
public Integer getHeaderTableSize() {
return headerTableSize;
}
public void setHeaderTableSize(Integer headerTableSize) {
this.headerTableSize = headerTableSize;
}
public Boolean getEnablePush() {
return enablePush;
}
public void setEnablePush(Boolean enablePush) {
this.enablePush = enablePush;
}
public Integer getMaxConcurrentStreams() {
return maxConcurrentStreams;
}
public void setMaxConcurrentStreams(Integer maxConcurrentStreams) {
this.maxConcurrentStreams = maxConcurrentStreams;
}
public Integer getInitialWindowSize() {
return initialWindowSize;
}
public void setInitialWindowSize(Integer initialWindowSize) {
this.initialWindowSize = initialWindowSize;
}
public Integer getMaxFrameSize() {
return maxFrameSize;
}
public void setMaxFrameSize(Integer maxFrameSize) {
this.maxFrameSize = maxFrameSize;
}
public Integer getMaxHeaderListSize() {
return maxHeaderListSize;
}
public void setMaxHeaderListSize(Integer maxHeaderListSize) {
this.maxHeaderListSize = maxHeaderListSize;
}
public void checkDefault() {
if (maxBodySize == null) {
maxBodySize = 1 << 23;
}
if (maxResponseBodySize == null) {
maxResponseBodySize = 1 << 23;
}
if (maxChunkSize == null) {
maxChunkSize = 1 << 23;
}
if (maxHeaderSize == null) {
maxHeaderSize = 8192;
}
if (maxInitialLineLength == null) {
maxInitialLineLength = 4096;
}
if (initialBufferSize == null) {
initialBufferSize = 16384;
}
if (headerTableSize == null) {
headerTableSize = 4096;
}
if (enablePush == null) {
enablePush = false;
}
if (maxConcurrentStreams == null) {
maxConcurrentStreams = Integer.MAX_VALUE;
}
if (initialWindowSize == null) {
initialWindowSize = 1 << 23;
}
if (maxFrameSize == null) {
maxFrameSize = 1 << 23;
}
if (maxHeaderListSize == null) {
maxHeaderListSize = 1 << 15;
}
}
}

View File

@ -0,0 +1,212 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.bootstrap.builders;
import org.apache.dubbo.config.nested.TripleConfig;
/**
* This is a builder for build {@link TripleConfig}.
*
* @since 3.3
*/
public class TripleBuilder {
/**
* Maximum allowed size for HTTP1 request bodies.
* Limits the size of request to prevent excessively large request.
* <p>The default value is 8MiB.
*/
private Integer maxBodySize;
/**
* Maximum allowed size for HTTP1 response bodies.
* Limits the size of responses to prevent excessively large response.
* <p>The default value is 8MiB.
*/
private Integer maxResponseBodySize;
/**
* Set the maximum chunk size.
* HTTP requests and responses can be quite large, in which case it's better to process the data as a stream of
* chunks.
* This sets the limit, in bytes, at which Netty will send a chunk down the pipeline.
* <p>The default value is 8KiB.
*/
private Integer maxChunkSize;
/**
* Set the maximum line length of header lines.
* This limits how much memory Netty will use when parsing HTTP header key-value pairs.
* You would typically set this to the same value as {@link #maxInitialLineLength(Integer)}.
* <p>The default value is 8KiB.
*/
private Integer maxHeaderSize;
/**
* Set the maximum length of the first line of the HTTP header.
* This limits how much memory Netty will use when parsed the initial HTTP header line.
* You would typically set this to the same value as {@link #maxHeaderSize(Integer)}.
* <p>The default value is 4096.
*/
private Integer maxInitialLineLength;
/**
* Set the initial size of the temporary buffer used when parsing the lines of the HTTP headers.
* <p>The default value is 128 octets.
*/
private Integer initialBufferSize;
/**
* The header table size.
*/
private Integer headerTableSize;
/**
* Whether to enable push, default is false.
*/
private Boolean enablePush;
/**
* Maximum concurrent streams.
*/
private Integer maxConcurrentStreams;
/**
* Initial window size.
*/
private Integer initialWindowSize;
/**
* Maximum frame size.
*/
private Integer maxFrameSize;
/**
* Maximum header list size.
*/
private Integer maxHeaderListSize;
public static TripleBuilder newBuilder() {
return new TripleBuilder();
}
public TripleBuilder maxBodySize(Integer maxBodySize) {
this.maxBodySize = maxBodySize;
return getThis();
}
public TripleBuilder maxResponseBodySize(Integer maxResponseBodySize) {
this.maxResponseBodySize = maxResponseBodySize;
return getThis();
}
public TripleBuilder maxChunkSize(Integer maxChunkSize) {
this.maxChunkSize = maxChunkSize;
return getThis();
}
public TripleBuilder maxHeaderSize(Integer maxHeaderSize) {
this.maxHeaderSize = maxHeaderSize;
return getThis();
}
public TripleBuilder maxInitialLineLength(Integer maxInitialLineLength) {
this.maxInitialLineLength = maxInitialLineLength;
return getThis();
}
public TripleBuilder initialBufferSize(Integer initialBufferSize) {
this.initialBufferSize = initialBufferSize;
return getThis();
}
public TripleBuilder headerTableSize(Integer headerTableSize) {
this.headerTableSize = headerTableSize;
return getThis();
}
public TripleBuilder enablePush(Boolean enablePush) {
this.enablePush = enablePush;
return getThis();
}
public TripleBuilder maxConcurrentStreams(Integer maxConcurrentStreams) {
this.maxConcurrentStreams = maxConcurrentStreams;
return getThis();
}
public TripleBuilder initialWindowSize(Integer initialWindowSize) {
this.initialWindowSize = initialWindowSize;
return getThis();
}
public TripleBuilder maxFrameSize(Integer maxFrameSize) {
this.maxFrameSize = maxFrameSize;
return getThis();
}
public TripleBuilder maxHeaderListSize(Integer maxHeaderListSize) {
this.maxHeaderListSize = maxHeaderListSize;
return getThis();
}
protected TripleBuilder getThis() {
return this;
}
public TripleConfig build() {
TripleConfig triple = new TripleConfig();
if (maxBodySize != null) {
triple.setMaxBodySize(maxBodySize);
}
if (maxResponseBodySize != null) {
triple.setMaxResponseBodySize(maxResponseBodySize);
}
if (maxChunkSize != null) {
triple.setMaxChunkSize(maxChunkSize);
}
if (maxHeaderSize != null) {
triple.setMaxHeaderSize(maxHeaderSize);
}
if (maxInitialLineLength != null) {
triple.setMaxInitialLineLength(maxInitialLineLength);
}
if (initialBufferSize != null) {
triple.setInitialBufferSize(initialBufferSize);
}
if (headerTableSize != null) {
triple.setHeaderTableSize(headerTableSize);
}
if (enablePush != null) {
triple.setEnablePush(enablePush);
}
if (maxConcurrentStreams != null) {
triple.setMaxConcurrentStreams(maxConcurrentStreams);
}
if (initialWindowSize != null) {
triple.setInitialWindowSize(initialWindowSize);
}
if (maxFrameSize != null) {
triple.setMaxFrameSize(maxFrameSize);
}
if (maxHeaderListSize != null) {
triple.setMaxHeaderListSize(maxHeaderListSize);
}
return triple;
}
}

View File

@ -35,6 +35,8 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasEntry;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
class ProtocolConfigTest {
@ -56,11 +58,35 @@ class ProtocolConfigTest {
}
@Test
void testName() throws Exception {
void testDefaultTripleConfig() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.refresh();
Map<String, String> parameters = new HashMap<>();
ProtocolConfig.appendParameters(parameters, protocol);
assertThat(parameters.isEmpty(), is(false));
// http2 default config
assertEquals(4096, Integer.parseInt(parameters.get("triple.header.table.size")));
assertFalse(Boolean.parseBoolean(parameters.get("triple.enable.push")));
assertEquals(Integer.MAX_VALUE, Integer.parseInt(parameters.get("triple.max.concurrent.streams")));
assertEquals(1 << 23, Integer.parseInt(parameters.get("triple.initial.window.size")));
assertEquals(1 << 23, Integer.parseInt(parameters.get("triple.max.frame.size")));
assertEquals(1 << 15, Integer.parseInt(parameters.get("triple.max.header.list.size")));
// http1 default config
assertEquals(1 << 23, Integer.parseInt(parameters.get("triple.max.body.size")));
assertEquals(1 << 23, Integer.parseInt(parameters.get("triple.max.response.body.size")));
assertEquals(1 << 23, Integer.parseInt(parameters.get("triple.max.chunk.size")));
assertEquals(8192, Integer.parseInt(parameters.get("triple.max.header.size")));
assertEquals(4096, Integer.parseInt(parameters.get("triple.max.initial.line.length")));
assertEquals(16384, Integer.parseInt(parameters.get("triple.initial.buffer.size")));
}
@Test
void testName() {
ProtocolConfig protocol = new ProtocolConfig();
String protocolName = "xprotocol";
protocol.setName(protocolName);
Map<String, String> parameters = new HashMap<String, String>();
Map<String, String> parameters = new HashMap<>();
ProtocolConfig.appendParameters(parameters, protocol);
assertThat(protocol.getName(), equalTo(protocolName));
assertThat(protocol.getId(), equalTo(null));
@ -68,7 +94,7 @@ class ProtocolConfigTest {
}
@Test
void testHost() throws Exception {
void testHost() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setHost("host");
Map<String, String> parameters = new HashMap<String, String>();
@ -78,21 +104,21 @@ class ProtocolConfigTest {
}
@Test
void testPort() throws Exception {
void testPort() {
ProtocolConfig protocol = new ProtocolConfig();
int port = NetUtils.getAvailablePort();
protocol.setPort(port);
Map<String, String> parameters = new HashMap<String, String>();
Map<String, String> parameters = new HashMap<>();
ProtocolConfig.appendParameters(parameters, protocol);
assertThat(protocol.getPort(), equalTo(port));
assertThat(parameters.isEmpty(), is(true));
}
@Test
void testPath() throws Exception {
void testPath() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setContextpath("context-path");
Map<String, String> parameters = new HashMap<String, String>();
Map<String, String> parameters = new HashMap<>();
ProtocolConfig.appendParameters(parameters, protocol);
assertThat(protocol.getPath(), equalTo("context-path"));
assertThat(protocol.getContextpath(), equalTo("context-path"));
@ -103,42 +129,42 @@ class ProtocolConfigTest {
}
@Test
void testCorethreads() throws Exception {
void testCorethreads() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setCorethreads(10);
assertThat(protocol.getCorethreads(), is(10));
}
@Test
void testThreads() throws Exception {
void testThreads() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setThreads(10);
assertThat(protocol.getThreads(), is(10));
}
@Test
void testIothreads() throws Exception {
void testIothreads() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setIothreads(10);
assertThat(protocol.getIothreads(), is(10));
}
@Test
void testQueues() throws Exception {
void testQueues() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setQueues(10);
assertThat(protocol.getQueues(), is(10));
}
@Test
void testAccepts() throws Exception {
void testAccepts() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setAccepts(10);
assertThat(protocol.getAccepts(), is(10));
}
@Test
void testCodec() throws Exception {
void testCodec() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setName("dubbo");
protocol.setCodec("mockcodec");
@ -146,84 +172,84 @@ class ProtocolConfigTest {
}
@Test
void testAccesslog() throws Exception {
void testAccesslog() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setAccesslog("access.log");
assertThat(protocol.getAccesslog(), equalTo("access.log"));
}
@Test
void testTelnet() throws Exception {
void testTelnet() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setTelnet("mocktelnethandler");
assertThat(protocol.getTelnet(), equalTo("mocktelnethandler"));
}
@Test
void testRegister() throws Exception {
void testRegister() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setRegister(true);
assertThat(protocol.isRegister(), is(true));
}
@Test
void testTransporter() throws Exception {
void testTransporter() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setTransporter("mocktransporter");
assertThat(protocol.getTransporter(), equalTo("mocktransporter"));
}
@Test
void testExchanger() throws Exception {
void testExchanger() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setExchanger("mockexchanger");
assertThat(protocol.getExchanger(), equalTo("mockexchanger"));
}
@Test
void testDispatcher() throws Exception {
void testDispatcher() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setDispatcher("mockdispatcher");
assertThat(protocol.getDispatcher(), equalTo("mockdispatcher"));
}
@Test
void testNetworker() throws Exception {
void testNetworker() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setNetworker("networker");
assertThat(protocol.getNetworker(), equalTo("networker"));
}
@Test
void testParameters() throws Exception {
void testParameters() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setParameters(Collections.singletonMap("k1", "v1"));
assertThat(protocol.getParameters(), hasEntry("k1", "v1"));
}
@Test
void testDefault() throws Exception {
void testDefault() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setDefault(true);
assertThat(protocol.isDefault(), is(true));
}
@Test
void testKeepAlive() throws Exception {
void testKeepAlive() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setKeepAlive(true);
assertThat(protocol.getKeepAlive(), is(true));
}
@Test
void testOptimizer() throws Exception {
void testOptimizer() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setOptimizer("optimizer");
assertThat(protocol.getOptimizer(), equalTo("optimizer"));
}
@Test
void testExtension() throws Exception {
void testExtension() {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setExtension("extension");
assertThat(protocol.getExtension(), equalTo("extension"));
@ -384,7 +410,7 @@ class ProtocolConfigTest {
}
@Test
void testPreferSerializationDefault1() throws Exception {
void testPreferSerializationDefault1() {
ProtocolConfig protocolConfig = new ProtocolConfig();
assertNull(protocolConfig.getPreferSerialization());
@ -400,7 +426,7 @@ class ProtocolConfigTest {
}
@Test
void testPreferSerializationDefault2() throws Exception {
void testPreferSerializationDefault2() {
ProtocolConfig protocolConfig = new ProtocolConfig();
assertNull(protocolConfig.getPreferSerialization());

View File

@ -35,6 +35,7 @@ import org.apache.dubbo.config.api.DemoService;
import org.apache.dubbo.config.deploy.DefaultApplicationDeployer;
import org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter;
import org.apache.dubbo.config.metadata.ExporterDeployListener;
import org.apache.dubbo.config.nested.TripleConfig;
import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.metadata.MetadataService;
@ -57,6 +58,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Properties;
import java.util.stream.Collectors;
@ -472,6 +474,50 @@ class DubboBootstrapTest {
});
}
@Test
void testDefaultTriple() {
ServiceConfig<DemoService> service = new ServiceConfig<>();
service.setInterface(DemoService.class);
service.setRef(new DemoServiceImpl());
TripleConfig triple = new TripleConfig();
triple.setMaxBodySize(50);
triple.setMaxResponseBodySize(100);
ProtocolConfig protocolConfig = new ProtocolConfig(CommonConstants.DUBBO_PROTOCOL, -1);
protocolConfig.setTriple(triple);
DubboBootstrap bootstrap = DubboBootstrap.getInstance();
bootstrap
.application(new ApplicationConfig("bootstrap-test"))
.registry(new RegistryConfig(zkServerAddress))
.protocol(protocolConfig)
.service(service)
.start();
TripleConfig tripleConfig = bootstrap
.getConfigManager()
.getProtocol(protocolConfig.getName())
.flatMap(protocol -> Optional.of(protocol.getTriple()))
.orElse(null);
// check custom value
Assertions.assertEquals(50, tripleConfig.getMaxBodySize());
Assertions.assertEquals(100, tripleConfig.getMaxResponseBodySize());
// check default value
Assertions.assertEquals(1 << 23, tripleConfig.getMaxChunkSize());
Assertions.assertEquals(8192, tripleConfig.getMaxHeaderSize());
Assertions.assertEquals(4096, tripleConfig.getMaxInitialLineLength());
Assertions.assertEquals(16384, tripleConfig.getInitialBufferSize());
Assertions.assertEquals(4096, tripleConfig.getHeaderTableSize());
Assertions.assertFalse(tripleConfig.getEnablePush());
Assertions.assertEquals(Integer.MAX_VALUE, tripleConfig.getMaxConcurrentStreams());
Assertions.assertEquals(1 << 23, tripleConfig.getInitialWindowSize());
Assertions.assertEquals(1 << 23, tripleConfig.getMaxFrameSize());
Assertions.assertEquals(1 << 15, tripleConfig.getMaxHeaderListSize());
}
private ExporterDeployListener getListener(ApplicationModel model) {
return (ExporterDeployListener)
model.getExtensionLoader(ApplicationDeployListener.class).getExtension("exporter");

View File

@ -0,0 +1,143 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.bootstrap.builders;
import org.apache.dubbo.config.nested.TripleConfig;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
class TripleBuilderTest {
@Test
void maxBodySize() {
TripleBuilder builder = TripleBuilder.newBuilder();
builder.maxBodySize(10240);
Assertions.assertEquals(10240, builder.build().getMaxBodySize());
}
@Test
void maxResponseBodySize() {
TripleBuilder builder = TripleBuilder.newBuilder();
builder.maxResponseBodySize(8192);
Assertions.assertEquals(8192, builder.build().getMaxResponseBodySize());
}
@Test
void maxChunkSize() {
TripleBuilder builder = TripleBuilder.newBuilder();
builder.maxChunkSize(2048);
Assertions.assertEquals(2048, builder.build().getMaxChunkSize());
}
@Test
void maxHeaderSize() {
TripleBuilder builder = TripleBuilder.newBuilder();
builder.maxHeaderSize(40960);
Assertions.assertEquals(40960, builder.build().getMaxHeaderSize());
}
@Test
void maxInitialLineLength() {
TripleBuilder builder = TripleBuilder.newBuilder();
builder.maxInitialLineLength(Integer.MAX_VALUE);
Assertions.assertEquals(Integer.MAX_VALUE, builder.build().getMaxInitialLineLength());
}
@Test
void initialBufferSize() {
TripleBuilder builder = TripleBuilder.newBuilder();
builder.initialBufferSize(3000);
Assertions.assertEquals(3000, builder.build().getInitialBufferSize());
}
@Test
void headerTableSize() {
TripleBuilder builder = TripleBuilder.newBuilder();
builder.headerTableSize(1000);
Assertions.assertEquals(1000, builder.build().getHeaderTableSize());
}
@Test
void enablePush() {
TripleBuilder builder = TripleBuilder.newBuilder();
builder.enablePush(false);
Assertions.assertFalse(builder.build().getEnablePush());
}
@Test
void maxConcurrentStreams() {
TripleBuilder builder = TripleBuilder.newBuilder();
builder.maxConcurrentStreams(3000);
Assertions.assertEquals(3000, builder.build().getMaxConcurrentStreams());
}
@Test
void initialWindowSize() {
TripleBuilder builder = TripleBuilder.newBuilder();
builder.initialWindowSize(10240);
Assertions.assertEquals(10240, builder.build().getInitialWindowSize());
}
@Test
void maxFrameSize() {
TripleBuilder builder = TripleBuilder.newBuilder();
builder.maxFrameSize(4096);
Assertions.assertEquals(4096, builder.build().getMaxFrameSize());
}
@Test
void maxHeaderListSize() {
TripleBuilder builder = TripleBuilder.newBuilder();
builder.maxHeaderListSize(2000);
Assertions.assertEquals(2000, builder.build().getMaxHeaderListSize());
}
@Test
void build() {
TripleBuilder builder = TripleBuilder.newBuilder();
builder.maxBodySize(2048)
.maxResponseBodySize(3072)
.maxChunkSize(10240)
.maxHeaderSize(400)
.maxInitialLineLength(100)
.initialBufferSize(8192)
.headerTableSize(300)
.enablePush(true)
.maxConcurrentStreams(Integer.MAX_VALUE)
.initialWindowSize(4096)
.maxFrameSize(1024)
.maxHeaderListSize(500);
TripleConfig config = builder.build();
TripleConfig config2 = builder.build();
Assertions.assertEquals(2048, config.getMaxBodySize());
Assertions.assertEquals(3072, config.getMaxResponseBodySize());
Assertions.assertEquals(10240, config.getMaxChunkSize());
Assertions.assertEquals(400, config.getMaxHeaderSize());
Assertions.assertEquals(100, config.getMaxInitialLineLength());
Assertions.assertEquals(8192, config.getInitialBufferSize());
Assertions.assertEquals(300, config.getHeaderTableSize());
Assertions.assertTrue(config.getEnablePush());
Assertions.assertEquals(Integer.MAX_VALUE, config.getMaxConcurrentStreams());
Assertions.assertEquals(4096, config.getInitialWindowSize());
Assertions.assertEquals(1024, config.getMaxFrameSize());
Assertions.assertEquals(500, config.getMaxHeaderListSize());
Assertions.assertNotSame(config, config2);
}
}

View File

@ -1134,6 +1134,80 @@
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="tripleType">
<xsd:attribute name="max-body-size" type="xsd:integer" default="8388608">
<xsd:annotation>
<xsd:documentation><![CDATA[ Maximum allowed size for HTTP1 request bodies. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="max-response-body-size" type="xsd:integer" default="8388608">
<xsd:annotation>
<xsd:documentation><![CDATA[ Maximum allowed size for HTTP1 response bodies. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="max-chunk-size" type="xsd:integer" default="8388608">
<xsd:annotation>
<xsd:documentation><![CDATA[ Set the maximum chunk size. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="max-header-size" type="xsd:integer" default="8192">
<xsd:annotation>
<xsd:documentation><![CDATA[ Set the maximum line length of header lines. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="max-initial-line-length" type="xsd:integer" default="4096">
<xsd:annotation>
<xsd:documentation><![CDATA[ Set the maximum length of the first line of the HTTP header. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="initial-buffer-size" type="xsd:integer" default="16384">
<xsd:annotation>
<xsd:documentation><![CDATA[ Set the initial size of the temporary buffer used when parsing the lines of the HTTP headers. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="header-table-size" type="xsd:integer" default="4096">
<xsd:annotation>
<xsd:documentation><![CDATA[ The header table size. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="enable-push" type="xsd:boolean" default="false">
<xsd:annotation>
<xsd:documentation><![CDATA[ Whether to enable push, default is false. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="max-concurrent-streams" type="xsd:integer" default="2147483647">
<xsd:annotation>
<xsd:documentation><![CDATA[ Maximum concurrent streams ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="initial-window-size" type="xsd:integer" default="8388608">
<xsd:annotation>
<xsd:documentation><![CDATA[ Whether to enable push, default is false. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="max-frame-size" type="xsd:integer" default="8388608">
<xsd:annotation>
<xsd:documentation><![CDATA[ Maximum concurrent streams ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="max-header-list-size" type="xsd:integer" default="32768">
<xsd:annotation>
<xsd:documentation><![CDATA[ Maximum header list size. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<xsd:complexType name="prometheusExporterType">
<xsd:attribute name="enabled" type="xsd:boolean">
<xsd:annotation>
@ -1508,6 +1582,7 @@
<xsd:complexType name="protocolType">
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element ref="parameter" minOccurs="0" maxOccurs="unbounded"/>
<xsd:element ref="triple" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="id" type="xsd:ID">
<xsd:annotation>
@ -2179,6 +2254,17 @@
</xsd:annotation>
</xsd:element>
<xsd:element name="triple" type="tripleType">
<xsd:annotation>
<xsd:documentation><![CDATA[ The triple config ]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation>
<tool:exports type="org.apache.dubbo.config.nested.TripleConfig"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="prometheus-exporter" type="prometheusExporterType">
<xsd:annotation>
<xsd:documentation><![CDATA[ The metrics prometheus exporter config. ]]></xsd:documentation>

View File

@ -97,12 +97,6 @@ public interface Constants {
String INVOCATION_KEY = "invocation";
String SERIALIZATION_ID_KEY = "serialization_id";
String H2_SETTINGS_HEADER_TABLE_SIZE_KEY = "dubbo.rpc.tri.header-table-size";
String H2_SETTINGS_ENABLE_PUSH_KEY = "dubbo.rpc.tri.enable-push";
String H2_SETTINGS_MAX_CONCURRENT_STREAMS_KEY = "dubbo.rpc.tri.max-concurrent-streams";
String H2_SETTINGS_INITIAL_WINDOW_SIZE_KEY = "dubbo.rpc.tri.initial-window-size";
String H2_SETTINGS_MAX_FRAME_SIZE_KEY = "dubbo.rpc.tri.max-frame-size";
String H2_SETTINGS_MAX_HEADER_LIST_SIZE_KEY = "dubbo.rpc.tri.max-header-list-size";
String H2_SETTINGS_SUPPORT_NO_LOWER_HEADER_KEY = "dubbo.rpc.tri.support-no-lower-header";
String H2_SETTINGS_IGNORE_1_0_0_KEY = "dubbo.rpc.tri.ignore-1.0.0-version";
String H2_SETTINGS_RESOLVE_FALLBACK_TO_DEFAULT_KEY = "dubbo.rpc.tri.resolve-fallback-to-default";

View File

@ -16,9 +16,7 @@
package org.apache.dubbo.rpc.protocol.tri;
import org.apache.dubbo.common.config.Configuration;
import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.config.nested.TripleConfig;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http2.Http2Connection;
@ -37,7 +35,6 @@ import io.netty.util.internal.logging.InternalLoggerFactory;
import java.util.ArrayDeque;
import java.util.Deque;
import static io.netty.handler.codec.http2.Http2CodecUtil.DEFAULT_WINDOW_SIZE;
import static io.netty.handler.codec.http2.Http2CodecUtil.MAX_WEIGHT;
import static io.netty.handler.codec.http2.Http2CodecUtil.MIN_WEIGHT;
import static io.netty.handler.codec.http2.Http2Error.FLOW_CONTROL_ERROR;
@ -49,47 +46,43 @@ import static io.netty.util.internal.ObjectUtil.checkNotNull;
import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static org.apache.dubbo.rpc.Constants.H2_SETTINGS_INITIAL_WINDOW_SIZE_KEY;
/**
* This design is learning from {@see io.netty.handler.codec.http2.DefaultHttp2RemoteFlowController} which is in Netty.
*/
@UnstableApi
public class TriHttp2RemoteFlowController implements Http2RemoteFlowController {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(TriHttp2RemoteFlowController.class);
private static final InternalLogger logger = InternalLoggerFactory.getInstance(TriHttp2RemoteFlowController.class);
private static final int MIN_WRITABLE_CHUNK = 32 * 1024;
private final Http2Connection connection;
private final Http2Connection.PropertyKey stateKey;
private final StreamByteDistributor streamByteDistributor;
private final FlowState connectionState;
private final Configuration config;
private int initialWindowSize;
private WritabilityMonitor monitor;
private ChannelHandlerContext ctx;
public TriHttp2RemoteFlowController(Http2Connection connection, ApplicationModel applicationModel) {
this(connection, (Listener) null, applicationModel);
public TriHttp2RemoteFlowController(Http2Connection connection, TripleConfig config) {
this(connection, (Listener) null, config);
}
public TriHttp2RemoteFlowController(Http2Connection connection,
StreamByteDistributor streamByteDistributor,
ApplicationModel applicationModel) {
this(connection, streamByteDistributor, null, applicationModel);
public TriHttp2RemoteFlowController(
Http2Connection connection, StreamByteDistributor streamByteDistributor, TripleConfig config) {
this(connection, streamByteDistributor, null, config);
}
public TriHttp2RemoteFlowController(Http2Connection connection, final Listener listener, ApplicationModel applicationModel) {
this(connection, new WeightedFairQueueByteDistributor(connection), listener, applicationModel);
public TriHttp2RemoteFlowController(Http2Connection connection, final Listener listener, TripleConfig config) {
this(connection, new WeightedFairQueueByteDistributor(connection), listener, config);
}
public TriHttp2RemoteFlowController(Http2Connection connection,
StreamByteDistributor streamByteDistributor,
final Listener listener,
ApplicationModel applicationModel) {
public TriHttp2RemoteFlowController(
Http2Connection connection,
StreamByteDistributor streamByteDistributor,
final Listener listener,
TripleConfig config) {
this.connection = checkNotNull(connection, "connection");
this.streamByteDistributor = checkNotNull(streamByteDistributor, "streamWriteDistributor");
this.config = ConfigurationUtils.getGlobalConfiguration(applicationModel);
this.initialWindowSize = config.getInt(H2_SETTINGS_INITIAL_WINDOW_SIZE_KEY, DEFAULT_WINDOW_SIZE);
this.initialWindowSize = config.getInitialWindowSize();
// Add a flow state for the connection.
stateKey = connection.newKey();
@ -414,9 +407,9 @@ public class TriHttp2RemoteFlowController implements Http2RemoteFlowController {
if (cancelled) {
cancel(INTERNAL_ERROR, cause);
}
if(monitor.isOverFlowControl()){
if (monitor.isOverFlowControl()) {
cause = new Throwable();
cancel(FLOW_CONTROL_ERROR,cause);
cancel(FLOW_CONTROL_ERROR, cause);
}
}
return writtenBytes;
@ -427,8 +420,7 @@ public class TriHttp2RemoteFlowController implements Http2RemoteFlowController {
*/
int incrementStreamWindow(int delta) throws Http2Exception {
if (delta > 0 && Integer.MAX_VALUE - delta < window) {
throw streamError(stream.id(), FLOW_CONTROL_ERROR,
"Window size overflow for stream: %d", stream.id());
throw streamError(stream.id(), FLOW_CONTROL_ERROR, "Window size overflow for stream: %d", stream.id());
}
window += delta;
streamByteDistributor.updateStreamableBytes(this);
@ -499,8 +491,8 @@ public class TriHttp2RemoteFlowController implements Http2RemoteFlowController {
FlowControlled frame = pendingWriteQueue.poll();
if (frame != null) {
// Only create exception once and reuse to reduce overhead of filling in the stacktrace.
final Http2Exception exception = streamError(stream.id(), error, cause,
"Stream closed before write could take place");
final Http2Exception exception =
streamError(stream.id(), error, cause, "Stream closed before write could take place");
do {
writeError(frame, exception);
frame = pendingWriteQueue.poll();
@ -572,13 +564,13 @@ public class TriHttp2RemoteFlowController implements Http2RemoteFlowController {
* Called when the writability of the underlying channel changes.
* @throws Http2Exception If a write occurs and an exception happens in the write operation.
*/
void channelWritabilityChange() throws Http2Exception { }
void channelWritabilityChange() throws Http2Exception {}
/**
* Called when the state is cancelled.
* @param state the state that was cancelled.
*/
void stateCancelled(FlowState state) { }
void stateCancelled(FlowState state) {}
/**
* Set the initial window size for {@code state}.
@ -644,10 +636,10 @@ public class TriHttp2RemoteFlowController implements Http2RemoteFlowController {
int bytesToWrite = writableBytes();
// Make sure we always write at least once, regardless if we have bytesToWrite or not.
// This ensures that zero-length frames will always be written.
for (;;) {
if (!streamByteDistributor.distribute(bytesToWrite, this) ||
(bytesToWrite = writableBytes()) <= 0 ||
!isChannelWritable0()) {
for (; ; ) {
if (!streamByteDistributor.distribute(bytesToWrite, this)
|| (bytesToWrite = writableBytes()) <= 0
|| !isChannelWritable0()) {
break;
}
}
@ -680,9 +672,9 @@ public class TriHttp2RemoteFlowController implements Http2RemoteFlowController {
}
final boolean isOverFlowControl() {
if(connectionState.windowSize() == 0){
if (connectionState.windowSize() == 0) {
return true;
}else {
} else {
return false;
}
}
@ -785,9 +777,12 @@ public class TriHttp2RemoteFlowController implements Http2RemoteFlowController {
checkAllWritabilityChanged();
} else if (isWritable(state) != state.markedWritability()) {
notifyWritabilityChanged(state);
}else if(isOverFlowControl()){
throw streamError(state.stream().id(), FLOW_CONTROL_ERROR,
"TotalPendingBytes size overflow for stream: %d", state.stream().id());
} else if (isOverFlowControl()) {
throw streamError(
state.stream().id(),
FLOW_CONTROL_ERROR,
"TotalPendingBytes size overflow for stream: %d",
state.stream().id());
}
}
@ -798,4 +793,3 @@ public class TriHttp2RemoteFlowController implements Http2RemoteFlowController {
}
}
}

View File

@ -17,9 +17,8 @@
package org.apache.dubbo.rpc.protocol.tri;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.Configuration;
import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.config.nested.TripleConfig;
import org.apache.dubbo.remoting.ChannelHandler;
import org.apache.dubbo.remoting.api.AbstractWireProtocol;
import org.apache.dubbo.remoting.api.pu.ChannelHandlerPretender;
@ -31,7 +30,6 @@ import org.apache.dubbo.remoting.http12.netty4.h1.NettyHttp1ConnectionHandler;
import org.apache.dubbo.remoting.http12.netty4.h2.NettyHttp2FrameCodec;
import org.apache.dubbo.remoting.http12.netty4.h2.NettyHttp2ProtocolSelectorHandler;
import org.apache.dubbo.remoting.utils.UrlUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ScopeModelAware;
import org.apache.dubbo.rpc.protocol.tri.h12.TripleProtocolDetector;
@ -47,6 +45,7 @@ import java.util.List;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.http.HttpDecoderConfig;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.HttpServerUpgradeHandler;
@ -62,25 +61,9 @@ import io.netty.handler.flush.FlushConsolidationHandler;
import io.netty.handler.logging.LogLevel;
import io.netty.util.AsciiString;
import static org.apache.dubbo.rpc.Constants.H2_SETTINGS_ENABLE_PUSH_KEY;
import static org.apache.dubbo.rpc.Constants.H2_SETTINGS_HEADER_TABLE_SIZE_KEY;
import static org.apache.dubbo.rpc.Constants.H2_SETTINGS_INITIAL_WINDOW_SIZE_KEY;
import static org.apache.dubbo.rpc.Constants.H2_SETTINGS_MAX_CONCURRENT_STREAMS_KEY;
import static org.apache.dubbo.rpc.Constants.H2_SETTINGS_MAX_FRAME_SIZE_KEY;
import static org.apache.dubbo.rpc.Constants.H2_SETTINGS_MAX_HEADER_LIST_SIZE_KEY;
@Activate
public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeModelAware {
// 1 MiB
private static final int MIB_1 = 1 << 20;
private static final int MIB_8 = 1 << 23;
private static final int KIB_32 = 1 << 15;
private static final int DEFAULT_MAX_HEADER_LIST_SIZE = KIB_32;
private static final int DEFAULT_SETTING_HEADER_LIST_SIZE = 4096;
private static final int DEFAULT_MAX_FRAME_SIZE = MIB_8;
private static final int DEFAULT_WINDOW_INIT_SIZE = MIB_8;
public static final Http2FrameLogger CLIENT_LOGGER = new Http2FrameLogger(LogLevel.DEBUG, "H2_CLIENT");
public static final Http2FrameLogger SERVER_LOGGER = new Http2FrameLogger(LogLevel.DEBUG, "H2_SERVER");
@ -103,18 +86,16 @@ public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeMo
@Override
public void configClientPipeline(URL url, ChannelOperator operator, ContextOperator contextOperator) {
Configuration config = ConfigurationUtils.getGlobalConfiguration(url.getOrDefaultApplicationModel());
TripleConfig tripleConfig = getTripleConfig(url);
final Http2FrameCodec codec = Http2FrameCodecBuilder.forClient()
.gracefulShutdownTimeoutMillis(10000)
.initialSettings(new Http2Settings()
.headerTableSize(
config.getInt(H2_SETTINGS_HEADER_TABLE_SIZE_KEY, DEFAULT_SETTING_HEADER_LIST_SIZE))
.pushEnabled(config.getBoolean(H2_SETTINGS_ENABLE_PUSH_KEY, false))
.maxConcurrentStreams(config.getInt(H2_SETTINGS_MAX_CONCURRENT_STREAMS_KEY, Integer.MAX_VALUE))
.initialWindowSize(config.getInt(H2_SETTINGS_INITIAL_WINDOW_SIZE_KEY, DEFAULT_WINDOW_INIT_SIZE))
.maxFrameSize(config.getInt(H2_SETTINGS_MAX_FRAME_SIZE_KEY, DEFAULT_MAX_FRAME_SIZE))
.maxHeaderListSize(
config.getInt(H2_SETTINGS_MAX_HEADER_LIST_SIZE_KEY, DEFAULT_MAX_HEADER_LIST_SIZE)))
.headerTableSize(tripleConfig.getHeaderTableSize())
.pushEnabled(tripleConfig.getEnablePush())
.maxConcurrentStreams(tripleConfig.getMaxConcurrentStreams())
.initialWindowSize(tripleConfig.getInitialWindowSize())
.maxFrameSize(tripleConfig.getMaxFrameSize())
.maxHeaderListSize(tripleConfig.getMaxHeaderListSize()))
.frameLogger(CLIENT_LOGGER)
.build();
// codec.connection().local().flowController().frameWriter(codec.encoder().frameWriter());
@ -148,17 +129,20 @@ public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeMo
}
private void configurerHttp1Handlers(URL url, List<ChannelHandler> handlers) {
final HttpServerCodec sourceCodec = new HttpServerCodec();
TripleConfig tripleConfig = getTripleConfig(url);
final HttpServerCodec sourceCodec = new HttpServerCodec(new HttpDecoderConfig()
.setMaxChunkSize(tripleConfig.getMaxChunkSize())
.setMaxHeaderSize(tripleConfig.getMaxHeaderSize())
.setMaxInitialLineLength(tripleConfig.getMaxInitialLineLength())
.setInitialBufferSize(tripleConfig.getInitialBufferSize()));
handlers.add(new ChannelHandlerPretender(sourceCodec));
// Triple protocol http1 upgrade support
handlers.add(new ChannelHandlerPretender(new HttpServerUpgradeHandler(
sourceCodec,
protocol -> {
if (AsciiString.contentEquals(Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME, protocol)) {
Configuration config =
ConfigurationUtils.getGlobalConfiguration(url.getOrDefaultApplicationModel());
return new Http2ServerUpgradeCodec(
buildHttp2FrameCodec(config, url.getOrDefaultApplicationModel()),
buildHttp2FrameCodec(url),
new HttpWriteQueueHandler(),
new FlushConsolidationHandler(64, true),
new TripleServerConnectionHandler(),
@ -172,7 +156,7 @@ public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeMo
// If the upgrade was successful, remove the message from the output list
// so that it's not propagated to the next handler. This request will
// be propagated as a user event instead.
handlers.add(new ChannelHandlerPretender(new HttpObjectAggregator(Integer.MAX_VALUE)));
handlers.add(new ChannelHandlerPretender(new HttpObjectAggregator(tripleConfig.getMaxBodySize())));
handlers.add(new ChannelHandlerPretender(new NettyHttp1Codec()));
handlers.add(new ChannelHandlerPretender(new NettyHttp1ConnectionHandler(
url, frameworkModel, DefaultHttp11ServerTransportListenerFactory.INSTANCE)));
@ -191,8 +175,7 @@ public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeMo
}
private void configurerHttp2Handlers(URL url, List<ChannelHandler> handlers) {
Configuration config = ConfigurationUtils.getGlobalConfiguration(url.getOrDefaultApplicationModel());
final Http2FrameCodec codec = buildHttp2FrameCodec(config, url.getOrDefaultApplicationModel());
final Http2FrameCodec codec = buildHttp2FrameCodec(url);
final Http2MultiplexHandler handler = buildHttp2MultiplexHandler(url);
handlers.add(new ChannelHandlerPretender(new HttpWriteQueueHandler()));
handlers.add(new ChannelHandlerPretender(codec));
@ -202,21 +185,26 @@ public class TripleHttp2Protocol extends AbstractWireProtocol implements ScopeMo
handlers.add(new ChannelHandlerPretender(new TripleTailHandler()));
}
private Http2FrameCodec buildHttp2FrameCodec(Configuration config, ApplicationModel applicationModel) {
private Http2FrameCodec buildHttp2FrameCodec(URL url) {
TripleConfig tripleConfig = getTripleConfig(url);
return TripleHttp2FrameCodecBuilder.forServer()
.customizeConnection((connection) -> connection
.remote()
.flowController(new TriHttp2RemoteFlowController(connection, applicationModel)))
.customizeConnection((connection) ->
connection.remote().flowController(new TriHttp2RemoteFlowController(connection, tripleConfig)))
.gracefulShutdownTimeoutMillis(10000)
.initialSettings(new Http2Settings()
.headerTableSize(
config.getInt(H2_SETTINGS_HEADER_TABLE_SIZE_KEY, DEFAULT_SETTING_HEADER_LIST_SIZE))
.maxConcurrentStreams(config.getInt(H2_SETTINGS_MAX_CONCURRENT_STREAMS_KEY, Integer.MAX_VALUE))
.initialWindowSize(config.getInt(H2_SETTINGS_INITIAL_WINDOW_SIZE_KEY, DEFAULT_WINDOW_INIT_SIZE))
.maxFrameSize(config.getInt(H2_SETTINGS_MAX_FRAME_SIZE_KEY, DEFAULT_MAX_FRAME_SIZE))
.maxHeaderListSize(
config.getInt(H2_SETTINGS_MAX_HEADER_LIST_SIZE_KEY, DEFAULT_MAX_HEADER_LIST_SIZE)))
.headerTableSize(tripleConfig.getHeaderTableSize())
.maxConcurrentStreams(tripleConfig.getMaxConcurrentStreams())
.initialWindowSize(tripleConfig.getInitialWindowSize())
.maxFrameSize(tripleConfig.getMaxFrameSize())
.maxHeaderListSize(tripleConfig.getMaxHeaderListSize()))
.frameLogger(SERVER_LOGGER)
.build();
}
private TripleConfig getTripleConfig(URL url) {
return url.getOrDefaultApplicationModel()
.getApplicationConfigManager()
.getOrAddProtocol(url.getProtocol())
.getTriple();
}
}

View File

@ -91,7 +91,6 @@ class ExceptionUtilsTest {
URL providerUrl = URL.valueOf("tri://127.0.0.1:" + availablePort + "/" + IGreeter2.class.getName())
.addParameter(CommonConstants.TIMEOUT_KEY, 10000);
;
ModuleServiceRepository serviceRepository =
applicationModel.getDefaultModule().getServiceRepository();

View File

@ -30,7 +30,7 @@ import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.RestConfig;
import org.apache.dubbo.config.SslConfig;
import org.apache.dubbo.config.TracingConfig;
import org.apache.dubbo.config.TripleConfig;
import org.apache.dubbo.config.nested.TripleConfig;
import java.util.LinkedHashMap;
import java.util.Map;