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(...)
Related
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.
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"));
}
When creating a standalone server in Java (not using a container like tomcat/jetty), what are the various techniques to keep the service running and not ending?
I have seen where people use a ServerSocket (since you will be communicating with the service presumably), and they use ServerSocket.accept() which blocks until it receives a message. And this is usually done in a while loop:
while(...) {
serverSocket.accept();
}
(http://docs.oracle.com/javase/6/docs/api/java/net/ServerSocket.html#accept())
Is this the only way? If not, what other ways are there and any pros/cons with it?
Are there any libraries that help with building your own service, or its pretty much roll your own.
There are various libraries that help you roll your own Windows/Unix service in Java:
Apache Commons Daemon
Akuma
Java Service Wrapper
How you keep the application running depends on the actual needs of your application. If your application is a server, you would normally want to listen for incoming connections which usually involves some sort of blocking/polling. How you do that again depends on the type of server you want to build. Of the generic solutions there's the ServerSocket class and its method accept() that you already mentioned. Another possibility is to use java.nio and implement a reactor which provides a single-threaded server that can handle multiple connections at once (see http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf for details), but may be a bit hard to grasp and debug.
What you probably want is a multi-threaded server.
Each time the server accepts a connection, the server creates a thread to handle sending/reciving to that client. If you do not use threads in your server, it will only be able to handle one connection at a time.
So, as you meantioned, the server loops infinitly and listens for incomming connections:
while(true){
serverSocket.accept();
ClientHandler c = new ClientHandler(serverSocket);
A instance of the class ClientHandler will be created each time a connection is accepted. This class implements Runnable, and loops for incomming messages using getInputStream and getOutputStream on that socket:
public class ClientHandler implements Runnable{
DataInputStream in;
DataOutputStream out;
//ClientHandler constructor
public ClientHandler(Socket s) throws IOException{
in= new DataInputStream(socket.getInputStream());
out=new DataOutputStream(socket.getOutputStream());
thread.start();
}
The run method:
public void run() {
while(true){
String temp="";
while ((temp = (String) in.readUTF()) != null){ // Read from the input stream each iteration. When temp is not null a message is recived
System.out.println(temp);
Please that the above code does not take into account different exceptions that might occur and is very basic. But it should give you a basic idea on how a server using Sockets can be implemented.
For a quick solution (in a testing environment only!) you can go for something often dubbed as "Enterprise Loop" (because it is too often found in production systems):
while (true)
try {
// do something
} catch (Throwable t) {
// maybe log
}
However, this is not good style in the production code.
(see [1] for a parody of that idiom)
To create a service, you want one of the libraries from this answer.
If you "just need multithreading", have a look into the Java concurrency framework. I stronly suggest reading Java Concurrency in Practice, as multi-threading is much more that just starting another thread and errors are hard to debug.
[1] http://blog.antiblau.de/2016/01/26/java-enterprise-loop/
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.
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.