Using EventLoopGroup in Netty with Multiple Channels - java

I am new to Netty but unfortunately there seems to be no detailed documentation/tutorial for a beginner.
I have multiple threads, each creating separate clients to connect to separate channels, using NettyChannelBuilder. The idea is that each channel will send & receive different kind of messages to/from different hosts. E.g. it looks like this:
class MyServiceClass{
void executeTasks() {
...
//here multiple tasks are executed in a for loop
executorService.execute(new Task(new Client());
...
}
}
class Client {
..
void connect() {
channel = NettyChannelBuilder.forAddress(host, port).build();
}
}
In this case, each task has its own client and clients are building their own channels to receive messages.
Should i create a single EventLoopGroup at executeTasks and give it to the Clients to be used while building their channel.
If this is the case, what is the advantage of using EventLoopGroup? What is it exactly doing at the background?

I'm not sure what you're asking. EventLoopGroups are just a grouping of threads used for netty. Using netty your clients will be on an EventLoopGroup and will be assigned to threads in a round robin matter so some may be on the same thread.
Personally I find the docs to be great but it's definitely not a framework designed for beginners.

Related

Netty-TCP-HTTP-MQTT design

I am trying to write a server-side java application that can accept tcp, http and mqtt communication (receive and send/ MongoDB as storage). From research, we decided that it could be a jar application based on Netty and paho for mqtt. We have 3 project using three of these protocols, therefore I am trying to unify the connection module. They each have different protocol style, for example:
-tcp: 0102330123456700
-http: HTTP POST /URL/count {"id":"02","count":"01234567"}
-mqtt: topic /02/count {"count":"01234567"}
Since we are a bit short of time, i am running them three in a silly but quick way---3 different thread listening to 3 different ports.
public class ServerLauncher {
public static void main(String[] args) {
NettyRestServer nettyRestServer = new NettyRestServer();
MqttServer mqttServer = new MqttServer();
EchoServer echoServer = new EchoServer();
new Thread(nettyRestServer,"HTTP Listening").start();
new Thread(mqttServer,"Mqtt Listening").start();
new Thread(echoServer,"socket Listening").start();
}
}
My questions are:
Since they are all based on tcp, is there a good way to manage them all together without wasting thread resource? maybe running just one thread for listening one port. I only find examples of single protocol.
For data storage, is it an okey design to push all the incoming messages to a concurrentHashMap across all thread/channels. Finally with a another thread running scheduled task, storage this concurrentHashMap into MongoDB and reset. or maybe use queue instead of concurrentHashMap
If you use Netty for all of these you can share the same EventLoopGroup for all servers which means all will share the same Threads.
You don't have to use three threads to start Server. You can do all of these in only one ServerBootstrap. And put the logic in ChannelHandler.
Netty's ChannelPipeline can dynamicly change ChannelHandler when getting the connecttion.
ctx.pipeline().addBefore(...)
ctx.pipeline().addAfter(...)
ctx.pipeline().remove(...)

How can I use an EventExecutorGroup with an NioDatagramChannel in Netty?

I'm new to Netty, but I've worked with NIO a bit recently.
I'm building a UDP server, and it seems from the examples I've tried that unlike the NioServerSocketChannel.class, when you use the NioDatagramChannel.class you cannot assign an EventLoopGroup workerGroup to handle the Datagrams once they've been accepted by the socket. My code, based on the Netty QuoteOfTheMoment server example looks like this:
public class PositionServer {
int port;
public PositionServer(int port) {
this.port = port;
System.out.println("Port set to " + this.port);
}
public void run() {
EventLoopGroup bossGroup = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(bossGroup).channel(NioDatagramChannel.class)
.handler(new PositionServerHandler());
System.out.println("Binding to port " + port);
bootstrap.bind(port).sync().channel().closeFuture().await();
} catch (InterruptedException e) {
bossGroup.shutdownGracefully();
e.printStackTrace();
}
}
public static void main(String[] args) {
new PositionServer(4000).run();
}
}
This works perfectly fine, right now the PositionServerHandler simply outputs the messages to the console.
I want to push the messages into a database, they're JSON strings, so I'd like to convert them to JSON first. I don't want to do the in the bossGroup as it'll block with the database accessing and JSON processing. But I can't see an obvious way to add a workerGroup.
Googling didn't reveal much either, except that my workerGroup in this case should probably be an EventExecutorGroup and not an EventLoopGroup, but I'm not even 100% certain about that.
In NIO, I would have two thread pools, and I'd use some sort of queue, one pool of threads would push Strings to the queue, the other would take Strings from the queue, convert them to JSON objects and push them to the database.
Can I do something similar in Netty?
In which case my PositionServerHandler.class would accept a queue in the constructor, and push either whole DatagramPackets to it, or the message contents, then have another EventLoopGroup/EventExecutorGroup to take those messages and push them to the database.
It seems that ServerBootstrap doesn't handle NioDatagramChannels for some reason, that doesn't make sense to me.
Is this feasible? Am I missing some obvious solution to this?
Can I do something similar in Netty?
Yes. But first a clarification of terminology. In typical TCP server samples, the "boss group" is the event loop group that does TCP accept. The "worker group" is the event loop group that does TCP receive. Since UDP sockets do not "accept", but they do receive, the distinction between boss group and worker group is meaningless, and in the cited example, the variable is just called "group". It performs the same function as "worker group" in a typical TCP server, namely, it processes the incoming data.
Keep in mind that a single NioEventLoopGroup contains a thread pool which can be configured to have any number of threads.
In NIO, I would have two thread pools, and I'd use some sort of queue...
You can use the same design. You are still using NIO after all - you just have Netty to help you. The NioEventLoop "worker" group is your "first" thread pool which pushes Strings to the queue. Create your second thread pool any way you want, either using the standard Java APIs or using a second netty event loop group which is not attached to any channel. Everything else remains the same.

Akka ZeroMQExtension create multiple connection with one zeromq socket

Is it possible to create socket with multiple outgoing (ingoing) connections using ZeroMQExtensions?
More about multiple connections in ZeroMQ guide.
upd:
I can't see equavalent sample with ZeroMQExtensions. In 0MQExtensions documnetation i found:
newPubSocket(socketParameters: Array[SocketOption]): ActorRef
Java API factory method to create the actor representing the ZeroMQ Publisher socket. You can pass in as many configuration options as you want and the order of the configuration options doesn't matter They are matched on type and the first one found wins.
PS: I don't known scala and just started reading akka documentation to understand I need Akka or not.
I found solution (it was not intuitive but works):
ActorRef subSocket = ZeroMQExtension.get(getContext().system())
.newSubSocket(null, new Listener(getSelf()), new Subscribe("health"));
#Override
public void preStart() {
super.preStart();
subSocket.tell(new Connect("tcp://127.0.0.1:1237"));
subSocket.tell(new Connect("tcp://127.0.0.1:1238"));
}

How does the Netty threading model work in the case of many client connections?

I intend to use Netty in an upcoming project. This project will act as both client and server. Especially it will establish and maintain many connections to various servers while at the same time serving its own clients.
Now, the documentation for NioServerSocketChannelFactory fairly specifies the threading model for the server side of things fairly well - each bound listen port will require a dedicated boss thread throughout the process, while connected clients will be handled in a non-blocking fashion on worker threads. Specifically, one worker thread will be able to handle multiple connected clients.
However, the documentation for NioClientSocketChannelFactory is less specific. This also seems to utilize both boss and worker threads. However, the documentation states:
One NioClientSocketChannelFactory has one boss thread. It makes a connection attempt on request. Once a connection attempt succeeds, the boss thread passes the connected Channel to one of the worker threads that the NioClientSocketChannelFactory manages.
Worker threads seem to function in the same way as for the server case too.
My question is, does this mean that there will be one dedicated boss thread for each connection from my program to an external server? How will this scale if I establish hundreds, or thousands of such connections?
As a side note. Are there any adverse side effects for re-using a single Executor (cached thread pool) as both the bossExecutor and workerExecutor for a ChannelFactory? What about also re-using between different client and/or server ChannelFactory instances? This is somewhat discussed here, but I do not find those answers specific enough. Could anyone elaborate on this?
This is not a real answer to your question regarding how the Netty client thread model works. But you can use the same NioClientSocketChannelFactory to create single ClientBootstrap with multiple ChannelPipelineFactorys , and in turn make a large number of connections. Take a look at the example below.
public static void main(String[] args)
{
String host = "localhost";
int port = 8090;
ChannelFactory factory = new NioClientSocketChannelFactory(Executors
.newCachedThreadPool(), Executors.newCachedThreadPool());
MyHandler handler1 = new MyHandler();
PipelineFactory factory1 = new PipelineFactory(handler1);
AnotherHandler handler2 = new AnotherHandler();
PipelineFactory factory2 = new PipelineFactory(handler2);
ClientBootstrap bootstrap = new ClientBootstrap(factory);
// At client side option is tcpNoDelay and at server child.tcpNoDelay
bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("keepAlive", true);
for (int i = 1; i<=50;i++){
if(i%2==0){
bootstrap.setPipelineFactory(factory1);
}else{
bootstrap.setPipelineFactory(factory2);
}
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host,
port));
future.addListener(new ChannelFutureListener()
{
#Override
public void operationComplete(ChannelFuture future) throws Exception
{
future.getChannel().write("SUCCESS");
}
});
}
}
It also shows how different pipeline factories can be set for different connections, so based on the connection you make you can tweak your encoders/decoders in the channel pipeline.
I am not sure your question has been answer. Here's my answer: there's a single Boss thread that is managing simultaneously all the pending CONNECTs in your app. It uses nio to process all the current connects in a single (Boss) thread, and then hands each successfully connected channel off to one of the workers.
Your question mainly concerns performance. Single threads scale very well on the client.
Oh, and nabble has been closed. You can still browse the archive there.

Server Listening on Multiple Ports [Java]

I am trying to figure out how to create a java program that can listen to multiple ports and perform different actions depending on which port the client speaks to.
I've seen and understand the basic client-server program:
http://systembash.com/content/a-simple-java-tcp-server-and-tcp-client/
Just to reiterate, I want to create this same relationship, but instead of the server only listening on one port and performing one action when it receives input, I want it to listen on multiple ports and depending which port the client connects and sends data to, perform a different action.
I'm hoping to make each port accept a GET and PUT command in the future, but for now I'm just trying to figure out how to set up the basic structure of the server which will be able to listen to multiple ports. I've tried googling, but I can't seem to find much, so any help is appreciated.
Thanks in advance.
-Anthony
The tutorial you've mentioned is very basic. You cannot write any reasonable server without using threads. In order to have two server sockets, you must spawn a new thread for each port, like this (pseudocode):
new Thread() {
public void run() {
ServerSocket server = new ServerSocket(6788);
while(true) {
Socket client1 = server.accept();
//handle client1
}
}.start();
and (notice the different port):
new Thread() {
public void run() {
ServerSocket server = new ServerSocket(6789);
while(true) {
Socket client1 = server.accept();
//handle client2
}
}.start();
Having client1 and client2 sockets you can handle them separately. Also, handling client connection should be done in a different thread so that you can serve multiple clients. Of course this code introduces a lot of duplication, but consider this as a starting point.
To wrap things up - if your goal is to implement HTTP GET and PUT, use servlet and get away from all this hustle.
A socket can only be open to a particular port, so you need multiple server sockets (e.g. 1 socket per port). I think you also need one thread per socket so that network activity on one socket doesn't interfere with activity on the others.
Are you implementing a server as an academic exercise? If not, I'd really really really really strongly recommend using a preexisting server, like Tomcat.
You could just open multiple server sockets of course.
You might also want to look at jboss netty which can help you implement protocols.

Categories

Resources