Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add experimental nio-transport plugin with http #26295

Closed
wants to merge 48 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
8cc3880
WIPD
Tim-Brooks Jul 29, 2017
7f0cc5a
WIP
Tim-Brooks Jul 29, 2017
8603ca7
WIP
Tim-Brooks Jul 30, 2017
72ea6a6
WIP
Tim-Brooks Jul 30, 2017
3d3f4d0
WIP
Tim-Brooks Jul 30, 2017
6e25fc7
Merge remote-tracking branch 'upstream/master' into embedded_http
Tim-Brooks Aug 6, 2017
ae7743b
WIP
Tim-Brooks Aug 7, 2017
85be496
WIP
Tim-Brooks Aug 9, 2017
e8f8a88
WIP
Tim-Brooks Aug 10, 2017
959773c
WIP
Tim-Brooks Aug 11, 2017
d9a5d80
WIP
Tim-Brooks Aug 11, 2017
024d51d
WIP
Tim-Brooks Aug 13, 2017
a3ad4f2
WIP
Tim-Brooks Aug 15, 2017
30f04ed
Merge remote-tracking branch 'upstream/master' into embedded_http
Tim-Brooks Aug 15, 2017
b04078d
WIP
Tim-Brooks Aug 15, 2017
58effd0
Merge remote-tracking branch 'upstream/master' into embedded_http
Tim-Brooks Aug 16, 2017
8c9a4d8
Merge remote-tracking branch 'upstream/master' into embedded_http
Tim-Brooks Aug 16, 2017
2280d7b
Cleanup close interaction
Tim-Brooks Aug 16, 2017
19b3c98
WIP
Tim-Brooks Aug 16, 2017
bca982a
WIP
Tim-Brooks Aug 17, 2017
683abbc
Read context tests
Tim-Brooks Aug 17, 2017
bbe84d8
Implement read indexes
Tim-Brooks Aug 17, 2017
575ef11
Remove comment
Tim-Brooks Aug 17, 2017
74ff853
Implement write context tests
Tim-Brooks Aug 17, 2017
5e7d770
Release netty byte buffers
Tim-Brooks Aug 17, 2017
511399a
Merge remote-tracking branch 'upstream/master' into embedded_http
Tim-Brooks Aug 17, 2017
bc54ef8
Implement some integration tests
Tim-Brooks Aug 17, 2017
e9baacf
WIP
Tim-Brooks Aug 17, 2017
ce2a7b9
WIP
Tim-Brooks Aug 18, 2017
125b0a8
Merge branch 'master' into embedded_http
Tim-Brooks Aug 18, 2017
39eb8de
Make gradle check run
Tim-Brooks Aug 18, 2017
257875b
Ensure that integration tests are working
Tim-Brooks Aug 18, 2017
f5e35af
Fix some visibility issues
Tim-Brooks Aug 18, 2017
95171b8
A few cleanups
Tim-Brooks Aug 18, 2017
5f75f38
Fix license
Tim-Brooks Aug 18, 2017
9d2ee29
Merge remote-tracking branch 'upstream/master' into embedded_http
Tim-Brooks Aug 21, 2017
40c4135
Make changes based on review
Tim-Brooks Aug 21, 2017
b92827d
Add bootstrap check
Tim-Brooks Aug 21, 2017
cfc5210
Merge remote-tracking branch 'upstream/master' into embedded_http
Tim-Brooks Aug 25, 2017
0712b1a
Merge remote-tracking branch 'upstream/master' into embedded_http
Tim-Brooks Sep 6, 2017
59ac55d
Merge remote-tracking branch 'upstream/master' into embedded_http
Tim-Brooks Sep 13, 2017
ce2451d
Fix issue from merge
Tim-Brooks Sep 13, 2017
5ef5948
Fix visibility issue with class used in x-pack
Tim-Brooks Sep 13, 2017
10cc809
Merge remote-tracking branch 'upstream/master' into embedded_http
Tim-Brooks Sep 13, 2017
859f2b6
Fix test
Tim-Brooks Sep 13, 2017
269d823
Merge remote-tracking branch 'upstream/master' into embedded_http
Tim-Brooks Sep 15, 2017
bd0a75c
Update for bootstrap changes
Tim-Brooks Sep 15, 2017
4bd22fb
Merge remote-tracking branch 'upstream/master' into embedded_http
Tim-Brooks Nov 6, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ project.rootProject.subprojects.findAll { it.parent.path == ':plugins' }.each {
if (subproj.path.startsWith(':plugins:repository-')) {
return
}
if (subproj.path.startsWith(':plugins:transport-nio')) {
return
}
subproj.afterEvaluate { // need to wait until the project has been configured
integTestCluster {
plugin subproj.path
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
import java.util.Set;
import java.util.stream.Collectors;

public class Netty4HttpRequest extends RestRequest {
public final class Netty4HttpRequest extends RestRequest {

private final FullHttpRequest request;
private final Channel channel;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ public Netty4HttpServerTransport(Settings settings, NetworkService networkServic
this.compressionLevel = SETTING_HTTP_COMPRESSION_LEVEL.get(settings);
this.pipelining = SETTING_PIPELINING.get(settings);
this.pipeliningMaxEvents = SETTING_PIPELINING_MAX_EVENTS.get(settings);
this.corsConfig = buildCorsConfig(settings);
this.corsConfig = Netty4CorsConfig.buildCorsConfig(settings);

// validate max content length
if (maxContentLength.getBytes() > Integer.MAX_VALUE) {
Expand Down Expand Up @@ -351,40 +351,6 @@ static int resolvePublishPort(Settings settings, List<TransportAddress> boundAdd
return publishPort;
}

// package private for testing
static Netty4CorsConfig buildCorsConfig(Settings settings) {
if (SETTING_CORS_ENABLED.get(settings) == false) {
return Netty4CorsConfigBuilder.forOrigins().disable().build();
}
String origin = SETTING_CORS_ALLOW_ORIGIN.get(settings);
final Netty4CorsConfigBuilder builder;
if (Strings.isNullOrEmpty(origin)) {
builder = Netty4CorsConfigBuilder.forOrigins();
} else if (origin.equals(ANY_ORIGIN)) {
builder = Netty4CorsConfigBuilder.forAnyOrigin();
} else {
Pattern p = RestUtils.checkCorsSettingForRegex(origin);
if (p == null) {
builder = Netty4CorsConfigBuilder.forOrigins(RestUtils.corsSettingAsArray(origin));
} else {
builder = Netty4CorsConfigBuilder.forPattern(p);
}
}
if (SETTING_CORS_ALLOW_CREDENTIALS.get(settings)) {
builder.allowCredentials();
}
String[] strMethods = Strings.tokenizeToStringArray(SETTING_CORS_ALLOW_METHODS.get(settings), ",");
HttpMethod[] methods = Arrays.asList(strMethods)
.stream()
.map(HttpMethod::valueOf)
.toArray(size -> new HttpMethod[size]);
return builder.allowedRequestMethods(methods)
.maxAge(SETTING_CORS_MAX_AGE.get(settings))
.allowedRequestHeaders(Strings.tokenizeToStringArray(SETTING_CORS_ALLOW_HEADERS.get(settings), ","))
.shortCircuit()
.build();
}

private TransportAddress bindAddress(final InetAddress hostAddress) {
final AtomicReference<Exception> lastException = new AtomicReference<>();
final AtomicReference<InetSocketAddress> boundSocket = new AtomicReference<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@
import io.netty.handler.codec.http.EmptyHttpHeaders;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpMethod;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.RestUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Map;
Expand All @@ -32,6 +36,14 @@
import java.util.concurrent.Callable;
import java.util.regex.Pattern;

import static org.elasticsearch.http.HttpTransportSettings.SETTING_CORS_ALLOW_CREDENTIALS;
import static org.elasticsearch.http.HttpTransportSettings.SETTING_CORS_ALLOW_HEADERS;
import static org.elasticsearch.http.HttpTransportSettings.SETTING_CORS_ALLOW_METHODS;
import static org.elasticsearch.http.HttpTransportSettings.SETTING_CORS_ALLOW_ORIGIN;
import static org.elasticsearch.http.HttpTransportSettings.SETTING_CORS_ENABLED;
import static org.elasticsearch.http.HttpTransportSettings.SETTING_CORS_MAX_AGE;
import static org.elasticsearch.http.netty4.cors.Netty4CorsHandler.ANY_ORIGIN;

/**
* Configuration for Cross-Origin Resource Sharing (CORS).
*
Expand Down Expand Up @@ -232,4 +244,37 @@ public String toString() {
", preflightHeaders=" + preflightHeaders + ']';
}

public static Netty4CorsConfig buildCorsConfig(Settings settings) {
if (SETTING_CORS_ENABLED.get(settings) == false) {
return Netty4CorsConfigBuilder.forOrigins().disable().build();
}
String origin = SETTING_CORS_ALLOW_ORIGIN.get(settings);
final Netty4CorsConfigBuilder builder;
if (Strings.isNullOrEmpty(origin)) {
builder = Netty4CorsConfigBuilder.forOrigins();
} else if (origin.equals(ANY_ORIGIN)) {
builder = Netty4CorsConfigBuilder.forAnyOrigin();
} else {
Pattern p = RestUtils.checkCorsSettingForRegex(origin);
if (p == null) {
builder = Netty4CorsConfigBuilder.forOrigins(RestUtils.corsSettingAsArray(origin));
} else {
builder = Netty4CorsConfigBuilder.forPattern(p);
}
}
if (SETTING_CORS_ALLOW_CREDENTIALS.get(settings)) {
builder.allowCredentials();
}
String[] strMethods = Strings.tokenizeToStringArray(SETTING_CORS_ALLOW_METHODS.get(settings), ",");
HttpMethod[] methods = Arrays.asList(strMethods)
.stream()
.map(HttpMethod::valueOf)
.toArray(size -> new HttpMethod[size]);
return builder.allowedRequestMethods(methods)
.maxAge(SETTING_CORS_MAX_AGE.get(settings))
.allowedRequestHeaders(Strings.tokenizeToStringArray(SETTING_CORS_ALLOW_HEADERS.get(settings), ","))
.shortCircuit()
.build();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.util.ReferenceCounted;

class HttpPipelinedResponse implements Comparable<HttpPipelinedResponse>, ReferenceCounted {
public class HttpPipelinedResponse implements Comparable<HttpPipelinedResponse>, ReferenceCounted {

private final FullHttpResponse response;
private final ChannelPromise promise;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;

final class ByteBufBytesReference extends BytesReference {
public final class ByteBufBytesReference extends BytesReference {

private final ByteBuf buffer;
private final int length;
Expand Down Expand Up @@ -65,7 +65,7 @@ public void writeTo(OutputStream os) throws IOException {
buffer.getBytes(offset, os, length);
}

ByteBuf toByteBuf() {
public ByteBuf toByteBuf() {
return buffer.duplicate();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public void testCorsConfig() {
.put(SETTING_CORS_ALLOW_HEADERS.getKey(), collectionToDelimitedString(headers, ",", prefix, ""))
.put(SETTING_CORS_ALLOW_CREDENTIALS.getKey(), true)
.build();
final Netty4CorsConfig corsConfig = Netty4HttpServerTransport.buildCorsConfig(settings);
final Netty4CorsConfig corsConfig = Netty4CorsConfig.buildCorsConfig(settings);
assertTrue(corsConfig.isAnyOriginSupported());
assertEquals(headers, corsConfig.allowedRequestHeaders());
assertEquals(methods, corsConfig.allowedRequestMethods().stream().map(HttpMethod::name).collect(Collectors.toSet()));
Expand All @@ -128,7 +128,7 @@ public void testCorsConfigWithDefaults() {
final Set<String> headers = Strings.commaDelimitedListToSet(SETTING_CORS_ALLOW_HEADERS.getDefault(Settings.EMPTY));
final long maxAge = SETTING_CORS_MAX_AGE.getDefault(Settings.EMPTY);
final Settings settings = Settings.builder().put(SETTING_CORS_ENABLED.getKey(), true).build();
final Netty4CorsConfig corsConfig = Netty4HttpServerTransport.buildCorsConfig(settings);
final Netty4CorsConfig corsConfig = Netty4CorsConfig.buildCorsConfig(settings);
assertFalse(corsConfig.isAnyOriginSupported());
assertEquals(Collections.emptySet(), corsConfig.origins().get());
assertEquals(headers, corsConfig.allowedRequestHeaders());
Expand Down
33 changes: 33 additions & 0 deletions plugins/transport-nio/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.
*/

esplugin {
description 'The nio transport.'
classname 'org.elasticsearch.transport.nio.NioPlugin'
}

dependencyLicenses.enabled = false

compileJava.options.compilerArgs << "-Xlint:-try"
compileTestJava.options.compilerArgs << "-Xlint:-rawtypes,-unchecked"

dependencies {
compile project(path: ':modules:transport-netty4', configuration: 'runtime')
compile project(path: ':test:framework', configuration: 'runtime')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is it in the test framework needed here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The nio transport classes are in test:framework. Selectors, channels, etc.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought they were going to move into this plugin?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I spoke to @s1monw about this last week, his preference was to leave the tcp version of the nio transport in test:framework for now for for testing.

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.elasticsearch.transport.nio;

import org.elasticsearch.bootstrap.BootstrapCheck;
import org.elasticsearch.bootstrap.BootstrapContext;

public class NioNotEnabledBootstrapCheck implements BootstrapCheck {

@Override
public BootstrapCheckResult check(BootstrapContext context) {
return BootstrapCheckResult.failure("The transport-nio plugin is experimental and not ready for production usage. It should " +
"not be enabled in production.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch 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.elasticsearch.transport.nio;

import org.elasticsearch.bootstrap.BootstrapCheck;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.network.NetworkModule;
import org.elasticsearch.common.network.NetworkService;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.http.HttpServerTransport;
import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.plugins.NetworkPlugin;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.transport.nio.http.NioHttpTransport;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

public class NioPlugin extends Plugin implements NetworkPlugin {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should add a bootstrap check to make sure nobody uses this in production just yet? ie a check that always fails with a good explain error

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a check.


public static final String NIO_TRANSPORT_NAME = "nio-transport";
public static final String NIO_HTTP_TRANSPORT_NAME = "nio-http-transport";

@Override
public List<Setting<?>> getSettings() {
return Arrays.asList(
NioHttpTransport.NIO_HTTP_WORKER_COUNT,
NioHttpTransport.NIO_HTTP_ACCEPTOR_COUNT,
NioTransport.NIO_WORKER_COUNT,
NioTransport.NIO_ACCEPTOR_COUNT
);
}

@Override
public Settings additionalSettings() {
final Settings.Builder settingsBuilder = Settings.builder();
settingsBuilder.put(NetworkModule.TRANSPORT_TYPE_KEY, NIO_TRANSPORT_NAME);
settingsBuilder.put(NetworkModule.HTTP_TYPE_KEY, NIO_HTTP_TRANSPORT_NAME);
return settingsBuilder.build();
}

@Override
public Map<String, Supplier<Transport>> getTransports(Settings settings, ThreadPool threadPool, BigArrays bigArrays,
CircuitBreakerService circuitBreakerService,
NamedWriteableRegistry namedWriteableRegistry,
NetworkService networkService) {
return Collections.singletonMap(NIO_TRANSPORT_NAME, () -> new NioTransport(settings, threadPool, networkService, bigArrays,
namedWriteableRegistry, circuitBreakerService));
}

@Override
public List<BootstrapCheck> getBootstrapChecks() {
return Collections.singletonList(new NioNotEnabledBootstrapCheck());
}

@Override
public Map<String, Supplier<HttpServerTransport>> getHttpTransports(Settings settings, ThreadPool threadPool, BigArrays bigArrays,
CircuitBreakerService circuitBreakerService,
NamedWriteableRegistry namedWriteableRegistry,
NamedXContentRegistry xContentRegistry,
NetworkService networkService,
HttpServerTransport.Dispatcher dispatcher) {
return Collections.singletonMap(NIO_HTTP_TRANSPORT_NAME,
() -> new NioHttpTransport(settings, networkService, bigArrays, threadPool, xContentRegistry, dispatcher));
}
}
Loading