-
Notifications
You must be signed in to change notification settings - Fork 254
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #188 from NiteshKant/master
Adding an option to use a threadpool for Request/Connection processing.
- Loading branch information
Showing
22 changed files
with
569 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 74 additions & 0 deletions
74
...mples/src/main/java/io/reactivex/netty/examples/http/cpuintensive/CPUIntensiveServer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* | ||
* Copyright 2014 Netflix, Inc. | ||
* | ||
* Licensed 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 io.reactivex.netty.examples.http.cpuintensive; | ||
|
||
import io.netty.buffer.ByteBuf; | ||
import io.reactivex.netty.RxNetty; | ||
import io.reactivex.netty.pipeline.PipelineConfigurators; | ||
import io.reactivex.netty.protocol.http.server.HttpServer; | ||
import io.reactivex.netty.protocol.http.server.HttpServerRequest; | ||
import io.reactivex.netty.protocol.http.server.HttpServerResponse; | ||
import io.reactivex.netty.protocol.http.server.RequestHandler; | ||
import rx.Observable; | ||
|
||
import java.util.Map; | ||
|
||
/** | ||
* @author Nitesh Kant | ||
*/ | ||
public final class CPUIntensiveServer { | ||
|
||
static final int DEFAULT_PORT = 8790; | ||
public static final String IN_EVENT_LOOP_HEADER_NAME = "in_event_loop"; | ||
|
||
private final int port; | ||
|
||
public CPUIntensiveServer(int port) { | ||
this.port = port; | ||
} | ||
|
||
public HttpServer<ByteBuf, ByteBuf> createServer() { | ||
HttpServer<ByteBuf, ByteBuf> server = | ||
RxNetty.newHttpServerBuilder(port, new RequestHandler<ByteBuf, ByteBuf>() { | ||
@Override | ||
public Observable<Void> handle(HttpServerRequest<ByteBuf> request, | ||
final HttpServerResponse<ByteBuf> response) { | ||
printRequestHeader(request); | ||
response.getHeaders().set(IN_EVENT_LOOP_HEADER_NAME, | ||
response.getChannelHandlerContext().channel().eventLoop() | ||
.inEventLoop()); | ||
response.writeString("Welcome!!"); | ||
return response.close(false); | ||
} | ||
}).pipelineConfigurator(PipelineConfigurators.<ByteBuf, ByteBuf>httpServerConfigurator()) | ||
.withRequestProcessingThreads(50) /*Uses a thread pool of 50 threads to process the requests.*/ | ||
.build(); | ||
return server; | ||
} | ||
|
||
public void printRequestHeader(HttpServerRequest<ByteBuf> request) { | ||
System.out.println("New request received"); | ||
System.out.println(request.getHttpMethod() + " " + request.getUri() + ' ' + request.getHttpVersion()); | ||
for (Map.Entry<String, String> header : request.getHeaders().entries()) { | ||
System.out.println(header.getKey() + ": " + header.getValue()); | ||
} | ||
} | ||
|
||
public static void main(final String[] args) { | ||
new CPUIntensiveServer(DEFAULT_PORT).createServer().startAndWait(); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
...-examples/src/main/java/io/reactivex/netty/examples/http/cpuintensive/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
Overview | ||
======== | ||
|
||
An example of how to write a server which does some CPU intensive or Blocking work and hence is not suitable for running | ||
the request processing in the channel's event loop. | ||
This is achieved by using netty's [`EventExecutorGroup`](https://github.com/netty/netty/blob/master/common/src/main/java/io/netty/util/concurrent/EventExecutorGroup.java) | ||
as a threadpool. | ||
`RxNetty` makes sure that the [`RequestHandler`](https://github.com/Netflix/RxNetty/blob/master/rx-netty/src/main/java/io/reactivex/netty/protocol/http/server/RequestHandler.java) | ||
as well as the subscribers of `HttpServerRequest`'s content happens on this executor. | ||
|
||
Running | ||
======= | ||
|
||
To run the example execute: | ||
|
||
``` | ||
$ cd RxNetty/rx-netty-examples | ||
$ ../gradlew runCpuIntensiveHttpServer | ||
``` | ||
|
||
and in another console: | ||
|
||
``` | ||
$ cd RxNetty/rx-netty-examples | ||
$ ../gradlew runCpuIntensiveHttpClient | ||
``` |
76 changes: 76 additions & 0 deletions
76
...amples/src/main/java/io/reactivex/netty/examples/tcp/cpuintensive/CPUIntensiveServer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
/* | ||
* Copyright 2014 Netflix, Inc. | ||
* | ||
* Licensed 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 io.reactivex.netty.examples.tcp.cpuintensive; | ||
|
||
import io.netty.util.concurrent.DefaultEventExecutorGroup; | ||
import io.reactivex.netty.RxNetty; | ||
import io.reactivex.netty.channel.ConnectionHandler; | ||
import io.reactivex.netty.channel.ObservableConnection; | ||
import io.reactivex.netty.channel.RxDefaultThreadFactory; | ||
import io.reactivex.netty.pipeline.PipelineConfigurators; | ||
import io.reactivex.netty.server.RxServer; | ||
import rx.Observable; | ||
import rx.functions.Func1; | ||
|
||
/** | ||
* @author Nitesh Kant | ||
*/ | ||
public final class CPUIntensiveServer { | ||
|
||
static final int DEFAULT_PORT = 8791; | ||
|
||
private final int port; | ||
|
||
public CPUIntensiveServer(int port) { | ||
this.port = port; | ||
} | ||
|
||
public RxServer<String, String> createServer() { | ||
RxServer<String, String> server = | ||
RxNetty.newTcpServerBuilder(port, new ConnectionHandler<String, String>() { | ||
@Override | ||
public Observable<Void> handle( | ||
final ObservableConnection<String, String> connection) { | ||
System.out.println("New client connection established."); | ||
connection.writeAndFlush("Welcome! \n\n"); | ||
return connection.getInput() | ||
.flatMap(new Func1<String, Observable<Void>>() { | ||
@Override | ||
public Observable<Void> call(String msg) { | ||
System.out.println("onNext: " + msg); | ||
msg = msg.trim(); | ||
if (!msg.isEmpty()) { | ||
return connection.writeAndFlush( | ||
"echo => " + msg + '\n'); | ||
} else { | ||
return Observable.empty(); | ||
} | ||
} | ||
}); | ||
} | ||
}) | ||
.pipelineConfigurator(PipelineConfigurators.textOnlyConfigurator()) | ||
.withEventExecutorGroup(new DefaultEventExecutorGroup(50, new RxDefaultThreadFactory( | ||
"rx-connection-processor"))) /*Uses 50 threads to process connections.*/ | ||
.build(); | ||
return server; | ||
} | ||
|
||
public static void main(final String[] args) { | ||
new CPUIntensiveServer(DEFAULT_PORT).createServer().startAndWait(); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
...y-examples/src/main/java/io/reactivex/netty/examples/tcp/cpuintensive/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
Overview | ||
======== | ||
|
||
An example of how to write a server which does some CPU intensive or Blocking work and hence is not suitable for running | ||
the connection processing in the channel's event loop. | ||
This is achieved by using netty's [`EventExecutorGroup`](https://github.com/netty/netty/blob/master/common/src/main/java/io/netty/util/concurrent/EventExecutorGroup.java) | ||
as a threadpool. | ||
`RxNetty` makes sure that the [`ConnectionHandler`](https://github.com/Netflix/RxNetty/blob/master/rx-netty/src/main/java/io/reactivex/netty/channel/ConnectionHandler.java) | ||
as well as the subscribers of `ObservableConnection`'s content happens on this executor. | ||
|
||
Running | ||
======= | ||
|
||
To run the example execute: | ||
|
||
``` | ||
$ cd RxNetty/rx-netty-examples | ||
$ ../gradlew runCpuIntensiveTcpServer | ||
``` | ||
|
||
and in another console: | ||
|
||
``` | ||
$ cd RxNetty/rx-netty-examples | ||
$ ../gradlew runCpuIntensiveTcpClient | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
...s/src/test/java/io/reactivex/netty/examples/http/cpuintensive/CpuIntensiveServerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
* Copyright 2014 Netflix, Inc. | ||
* | ||
* Licensed 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 io.reactivex.netty.examples.http.cpuintensive; | ||
|
||
import io.netty.buffer.ByteBuf; | ||
import io.netty.handler.codec.http.HttpResponseStatus; | ||
import io.reactivex.netty.examples.ExamplesEnvironment; | ||
import io.reactivex.netty.examples.http.helloworld.HelloWorldClient; | ||
import io.reactivex.netty.protocol.http.server.HttpServer; | ||
import org.junit.After; | ||
import org.junit.Assert; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import static io.reactivex.netty.examples.http.cpuintensive.CPUIntensiveServer.DEFAULT_PORT; | ||
|
||
/** | ||
* @author Tomasz Bak | ||
*/ | ||
public class CpuIntensiveServerTest extends ExamplesEnvironment { | ||
|
||
private HttpServer<ByteBuf, ByteBuf> server; | ||
|
||
@Before | ||
public void setupHttpHelloServer() { | ||
server = new CPUIntensiveServer(DEFAULT_PORT).createServer(); | ||
server.start(); | ||
} | ||
|
||
@After | ||
public void stopServer() throws InterruptedException { | ||
server.shutdown(); | ||
} | ||
|
||
@Test | ||
public void testRequestReplySequence() { | ||
HelloWorldClient client = new HelloWorldClient(DEFAULT_PORT); // The client is no different than hello world. | ||
HttpResponseStatus statusCode = client.sendHelloRequest(); | ||
Assert.assertEquals(HttpResponseStatus.OK, statusCode); | ||
} | ||
} |
55 changes: 55 additions & 0 deletions
55
...es/src/test/java/io/reactivex/netty/examples/tcp/cpuintensive/CPUIntensiveServerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
/* | ||
* Copyright 2014 Netflix, Inc. | ||
* | ||
* Licensed 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 io.reactivex.netty.examples.tcp.cpuintensive; | ||
|
||
import io.reactivex.netty.examples.ExamplesEnvironment; | ||
import io.reactivex.netty.examples.tcp.echo.TcpEchoClient; | ||
import io.reactivex.netty.server.RxServer; | ||
import org.junit.After; | ||
import org.junit.Assert; | ||
import org.junit.Before; | ||
import org.junit.Test; | ||
|
||
import java.util.List; | ||
|
||
import static io.reactivex.netty.examples.tcp.cpuintensive.CPUIntensiveServer.DEFAULT_PORT; | ||
|
||
/** | ||
* @author Tomasz Bak | ||
*/ | ||
public class CPUIntensiveServerTest extends ExamplesEnvironment { | ||
|
||
private RxServer<String, String> server; | ||
|
||
@Before | ||
public void setupServer() { | ||
server = new CPUIntensiveServer(DEFAULT_PORT).createServer(); | ||
server.start(); | ||
} | ||
|
||
@After | ||
public void stopServer() throws Exception { | ||
server.shutdown(); | ||
} | ||
|
||
@Test | ||
public void testRequestReplySequence() { | ||
TcpEchoClient client = new TcpEchoClient(DEFAULT_PORT); | ||
List<String> reply = client.sendEchos(); | ||
Assert.assertEquals(10, reply.size()); | ||
} | ||
} |
Oops, something went wrong.