I am using DefaultEventExecutorGroup to execute business handler methods. My understanding is, IO event loop thread will enqueue events to DefaultEventExecutorGroup for execution. And any thread from DefaultEventExecutorGroup will poll those events, and executes handler methods when such event arises. If, so, then different threads from DefaultEventExecutorGroup can executing same channel handler methods. So, I need to synchronize channelRead() write() methods. Is it true? Or it is that, always only one of thread from DefaultEventExecutorGroup will always be executing handler methods, same like one of IO event loop thread always handles channel operations, that is, channel handler is always bound to single same thread only, even when there are multiple event executor groups in pipeline?
Going through the Netty 4 release guide, I see some information around the threading model that has been introduced since 4.0 release. Based on my understanding of it, below is my view:
different threads from DefaultEventExecutorGroup can executing same
channel handler methods.
Once a thread is assigned to a handler, this thread-handler link will continue until de-registration. The handler methods will always be invoked by the same thread.
channel handler is always bound to single same thread only, even when
there are multiple event executor groups in pipeline?
If two handlers in the same pipeline are assigned with different EventExecutors, they are invoked simultaneously. A user has to pay attention to thread safety if more than one handler access shared data even if the shared data is accessed only by the handlers in the same pipeline.
To test this scenario, I tried with NettyServer that has two handlers each with its own DefaultEventExecutorGroup. These handlers write and flush to the underlying channel character by character with a delay of 100 ms. First handler writes "Hello" and second one does a " WORLD !!!".
Server Code:
EventLoopGroup group = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(group).channel(NioServerSocketChannel.class).localAddress(new InetSocketAddress(port))
.childHandler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new DefaultEventExecutorGroup(10), new EchoServerHandler("Hello"));
ch.pipeline().addLast(new DefaultEventExecutorGroup(10), new EchoServerHandler(" WORLD !!!"));
}
});
Server Handler code:
for(int i = 0; i < message.length(); i++) {
ctx.write(Unpooled.copiedBuffer(new byte[] {message.getBytes()[i]}));
ctx.flush();
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
On the client side once the connection is established and I see the output is jumbled like HeWlOlRoLD !!!, H eWlORlLoD !!! etc. I believe this is the scenario you are asking.
Please refer to the Well-defined thread model and Write Ordering - Mix EventLoop thread and other threads sections of the following link regarding the Netty 4.0 threading model for more information.
Related
For the last week I read documentation about vertx. What i don't get it's how vertx handlers are work? For example
public class Client extends AbstractVerticle{
#Override
public void start() throws Exception {
final HttpClient httpClient = this.vertx.createHttpClient();
this.vertx.setPeriodic(1000, handler->{
httpClient.getNow(8080, "localhost", "/", responseHandler -> {
System.out.println("response");
});
});
}
}
And server is:
public class JdbcVertx extends AbstractVerticle{
#Override
public void start() throws Exception {
JDBCClient client = JDBCClient.createNonShared(this.vertx, new JsonObject()
.put("url", "jdbc:postgresql://localhost:5432/test")
.put("user", "user")
.put("password", "password")
.put("driver_class", "org.postgresql.Driver")
.put("max_pool_size", 30));
this.vertx.createHttpServer()
.requestHandler(r -> {
client.getConnection(handler -> {
final SQLConnection connection = handler.result();
connection.execute(execute(), hndlr -> {
connection.close(closehndlr -> {
r.response().putHeader("content-type", "text/html").end("Response");
});
});
});
}).listen(8080);
}
private String execute(){
return "insert into rubish (name) values ('test')";
}
}
(P.S i know that i firstly should to check if handler is succeded and then make some action but i remove this checking to simplify code and also from official docs if there is no any response during 30 sec there will be an exception in handler)
From the code above, client send request each second and doesn't wait for response , but it has a handler that will be executed when response was comming.
'JdbcVertx' listen on port 8080 , get request, make insertion to db with sleep for example 3 s (i put 1_000_000 rows to db and create index to slow down insertion time) and then send response, therefore each request is non blocking.
As i know , vertx has only one thread named EventLoop event loop from jdbcVertx get reqests but doesn't return response immediately , instead it put a handler that will be executed when db insertion was succeed. How event loop know when IO action is done. I think that it use somthing like this
if(Thread.currentThread().getState != 'blocked' && sec != 30){
this.object.getHandler().execute();
} else if(sec == 30){
Thread.currentThread.inerrupt();
} else{
sec++;
}
But we have only one thread, and when we have blocking call it doesn't has a thread, only handler.
The problem is , how event loop know when blocking operation is ended and it's time to execute handler
But we have only one thread, and when we have blocking call it doesn't has a thread, only handler. How it work , and why do we need to use Worker Verticle if we can use handlers instead?
The handlers are just actions triggered upon receipt of an eventbus message or an http call. They are not designed to handle scalability for you. If you only use handlers and if your actions starts to take a long time or if you have any increase in the number of requests, you will block the eventloop of your verticle and will have a lot of Thread xxxx has been blocked warns.
To answer on how handler works and why the event loop doesn't wait the end of a handler to start another, according to this : https://vertx.io/docs/vertx-core/java/#_reactor_and_multi_reactor
Instead of a single event loop, each Vertx instance maintains several event loops. By default we choose the number based on the number of available cores on the machine, but this can be overridden.
This means a single Vertx process can scale across your server, unlike Node.js.
We call this pattern the Multi-Reactor Pattern to distinguish it from the single threaded reactor pattern.
But that's not enough to handle all scalability and thread blocking problematics for you in my opinion, you schould read this too : https://vertx.io/docs/vertx-core/java/#golden_rule
There are many ways to design verticles but you have to stay as non-blocking as possible. In my opinion, using vert.x with a traditional blocking approach (like blocking restfull endpoints for example) is not relevant.
Personally I'd design my verticles as follows :
verticle A : which expose a restfull endpoint and take a callback url (whatever the action GET/POST/PUT/PATCH/DELETE). The verticle always respond a 202 Accepted immediatly without result and send a message in the eventbus to a verticle B.
verticle B : get the message, do the action (eventually invoke other verticles asynchronously with the eventbus and waiting the replies) and reply invoking the callback url.
I'd avoid to use worker verticle or the executeBlocking method or even creating a pool of thread. I'd privilege multiplying the instances of my verticles B (in seperate pids) that listen to the same eventbus cluster (and eventually verticle A with a http reverse proxy). We can even imagine having a variable number of verticle B instances (in seperate pids) depending on the number of requests in real time.
P.S : sometimes I use a more powerfull message broker tool like Apache Kafka instead of the native eventbus (when I need to respect a sort of message, or when I need to replay some messages).
Answering the question:
how event loop know when blocking operation is ended and it's time to execute handler?
According to the non-blocking model, the event-loop upon the call
connection.execute( execute(), hndlr )
spawns a new thread, executes your blocking piece of code and upon it's completion (something like Thread.join()) invokes the hndlr callback in the event-loop thread. Thus the main loop doesn't get blocked although the blocking code can be executed.
I have a socket server that uses an ExecutorService to create a new thread for each new socket. I also have a static instance of a class that makes database calls that all threads use.
My server is used for online chess matches. When a user makes a move, the move is sent to the server and an entry is made in the DB with general information about the move (including the ID of the match). Every 10 seconds or so, if the match's other client also has an active socket to the server, it will ask the server to fetch all new data about the match.
It works, but as you can imagine gets pretty inefficient if a non-trivial number of players are connected. What I want is a way for a thread to peek into the thread pool and find another thread based off an ID (The ID of the client for whom the thread is used), then call a method on that thread to send a message to the opposing player.
I've been looking all over, and I've had no luck. Is such a thing possible? If it is, is it advisable? Even if it's a bit risky code-wise, I'm willing to take extra steps to mitigate the risk for the enormous resource-saving benefits.
Like I said in my comment, your question is confusing; if all you're trying to do is to notify the opponent when a player makes a move, the simplest implementation is to use a BlockingQueue. The Javadoc even has code examples, so it should be fairly easy to implement. In your case, whenever a player makes a move, you put an item in the queue, that the consumer picks up and notifies the opponent that is participating in the same game. You don't need to mess with low level thread constructs, and if you're even thinking of finding threads based on ids from a pool, you're doing it all wrong.
The BlockingQueue would work, but it involves busy wait, so I'm not a big fan of it. Instead, you can use the Observer design pattern; the JDK already has support for this. Following is an example that I made up:
public class Main extends Observable implements Observer {
private final int numCores = Runtime.getRuntime().availableProcessors();
private final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(numCores);
public Main() {
addObserver(this);
}
public static void main(String[] args) throws InterruptedException {
new Main().execute();
}
private void execute() {
for (int i = 0; i < 5; ++i) {
this.setChanged();
this.notifyObservers(i);
try {
Thread.sleep(1000l);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
#Override
public void update(Observable o, Object arg) {
System.out.printf("Received notification on thread: %s.\n", Thread.currentThread().getName());
executor.submit(() -> System.out.printf("Running in thread: %s, result: %s.\n",
Thread.currentThread().getName(), arg));
}
}
Received notification on thread: main.
Running in thread: pool-1-thread-1, result: 0.
Received notification on thread: main.
Running in thread: pool-1-thread-2, result: 1.
Received notification on thread: main.
Running in thread: pool-1-thread-3, result: 2.
Received notification on thread: main.
Running in thread: pool-1-thread-4, result: 3.
Received notification on thread: main.
Running in thread: pool-1-thread-5, result: 4.
Last but not the least, if you really want to take it up a notch, use messaging. You didn't mention if you're using a framework (again, lack of information on your part), but Spring supports messaging, so does Akka, Play and Camel.
You may create the ExecutorService supplying your own ThreadFactory able to create your istantiate your own class that extends Thread and has a reference to the ThreadFactory itself. The ThreadFactory should trak all created Thread and be able to identify them by their ID. Such a way, each Thread will be able to query the ThreadFactory for some ID.
I have a servlet, and it is a singleton.
In the init, I create the producer and the consumers.
consumer = new MyThread();
consumer.start();
and the method run is like this:
#Override
public void run() {
while (!isShutdown()) {
if (queue.isEmpty())
queue.wait();
else
...
}
}
then i have the destroy method.
that set shutdown to true and I use .join
consumer.setShutdown(true);
consumer.join();
but the method .join got lock.. and never finishes.
If I change the queue.wait to Thread.sleep(), it works... but I don't want to change... what I'm doing wrong?
if I don't finish the thread, I got it:
SEVERE: The web application [/test] appears to have started a thread named [Comsumer0] but has failed to stop it. This is very likely to create a memory leak.
Using wait/notify methods is the old way to create a Consumer-Producer pattern.
It is better to use BlockingQueue.
BlockingQueue.put() - for Producer, and BlockingQueue.poll() - for Consumer.
BlockingQueue hides wait method underneath BlockingQueue.poll, BlockingQueue.put and will block a Consumer thread until Producer adds value to queue.
To fix the example above, you should make it wait for a finite amount of time like queue.wait(1000), or wake consumer thread explicitly calling queue.notify().
Most likely the queue is empty and since you have shutdown you never send anything into the queue to cause it to wake up.
Fix this either by sending a dummy message to the queue after setting the shutdown flag or by just removing the shutdown flag completely and sending a shutdown command to the queue.
Also be aware that if your shutdown flag is not volatile (or AtomicBoolean) then one thread may not see it being set by the other due to caching inside the CPU.
This is what the BlockingQueue is for:
BlockingQueue queue = new ArrayBlockingQueue(5);
// ...
while (!isShutdown()) {
Object poll = queue.poll(5, TimeUnit.SECONDS);
}
you should change the design as advised above, or if you don't want to change your code, change your setShutdown() method body and statement to notify the queue.
public void setShutdown(boolean shutdown) {
this.shutdown = shutdown;
this.queue.notifyAll();
}
I haven't got any code at the moment but I have a situation where I will be implementing an Java application onto a wireless sensor. There can only be one main method.
There will be multiple other wireless sensors that can connect to my sensor. My sensor needs to do a calculation based on thhe information provided to me by the other sensors. Each sensor can choose whether or not they want to participate in the calculation. Every 1 second, my sensor does a calculation.
So basically, what I need is to listen for incoming sensors, provide them with a thread to interact with, and retrieve the information from each sensor.
My question is, in my application, how do I listen for incoming sensors (blocking call) and also free my application to carry out its calculations?
From a high level, this is what your application will do
==Main Thread==
start socket
Start processing thread
accept an incoming connection (this will cause the thread to block until a connection occurs)
start new thread to handle socket (handler thread) (alternatively use a thread pool, but that is more complicated)
return to 3
==Handler Thread==
Receive open socket from main thread
Save data coming in from socket to be given to processing thread
Finish and close socket
==Processing Thread==
Wait 1 second
Process data retrieved from step 2 of Handler Thread
Return to 1
You need another thread that receives the information of all the communication threads. You should look at the utilities in java.util.concurrent such a BlockingQueue that let threads pass data to one another thread-safely.
Most of all you should read a lot about multi-threading: it is not a trivial topic.
This will get you started. Add error/exception checking/handling as necessary.
public class Test {
static class WorkTask42 implements Runnable {
public void run() {
// background work
}
}
public static void main(String... args) throws Exception {
// repeat for each background task
WorkTask42 wt = new WorkTask42();
Thread a = new Thread(wt);
a.setDeamon(true);
a.start();
}
}
I have a basic question. Why and how SelectableChannel's register method can be in blocking call.
Let me provide a scenario.
I have created a Selector object in class Register as follows.
private static Selector selector = Selector.open();
I also have a method in same class(Register) to register the channel with the selector.
public static SelectionKey registerChannel(SelectableChannel channel, int ops)
throws IOException {
channel.configureBlocking(false);
return channel.register(selector, ops);
}
And there is another class named Request, which has method which reads the data from channels, processes and calls following method to register the channel.
selectonKey = Register.register(socketChannel, SelectionKey.OP_READ);
Here at this point the thread is blocked, not giving clue of what it is waiting for.
I have verified that the selector is open. Please provide me some help to understand how can I resolve this. Is there any lock that I can release.
Any input would be appreciated.
Adding to what I described. Further tests revealed that if the Register.register method is called from the same thread, it is able to register but after that if some other thread tries to invoke the method, thread doesn,t move ahead.
This is a basic feature of most NIO implementations that isn't obvious from the documentation.
You need to make all register calls from the same thread that is doing your selecting or deadlocks will occur. Usually this is done by providing a queue of registrations/deregistrations/interest-changes that is written to and then selector.wakeup() is called. When the selecting thread wakes up it checks the queue and performs any requested operations.
You need to use a lock and manually synchronize.
In the same thread you are running the selector loop have a ReentrantLock:
final ReentrantLock selectorLock = new ReentrantLock();
Then when you need to register with the selector do something like this:
selectorLock.lock();
try {
selector.wakeup();
socketChannel.register(selector, ops);
} finally {
selectorLock.unlock();
}
Finally, during your loop that you are calling accept(), something like this:
selectorLock.lock();
selectorLock.unlock();
selector.select(500);
And then continue on with the rest of your logic.
This construct guarantees that the register() call will not block by ensuring that there is never another select() between corresponding wakeup() and register() calls.
I agree with #Darron's answer that you should pass register calls to the selector thread, but you should not use selector.wakeup as it would introduce race conditions (imagine selector thread was busying processing other registrations and your wakeup fail to wake up anyone). Luckily, Java NIO provided Pipe so that you can let the selector listen for both register calls and other events.
Basically, here's what needs to be done:
val registrationPipe = Pipe.open()
registrationPipe.source().configureBlocking(false)
registrationPipe.source().register(selector, SelectionKey.OP_READ)
// now start your selector thread
// now to register a call from other threads using message pleaseRegisterMe
registrationPipe.sink().write(pleaseRegisterMe)
// inside your selector thread
val selectionKey = iterator.next()
if (selectionKey.channel() === registrationPipe.source()) {
registrationPipe.source().read(pleaseRegisterMe)
// do something with the message pleaseRegisterMe and do the actual register
}
Here is a full working example.
Have you tried printing a stack trace of all threads in your program (using either kill -QUIT in Unix or Ctrl+Break in Windows or using the jstack utility)?
AbstractSelectableChannel contains a lock on which configureBlocking and register need to synchronize. This lock also is accessible through the blockingLock() method, and so another thread could potentially be holding the lock causing your register call to block indefinitely (but without a stack trace it's difficult to tell).
Register your channel from any thread:
synchronized (selectorLock2) {
selector.wakeup();
synchronized (selectorLock1) {
channel.register(selector, ops);
}
}
Your selector loop should look like this:
while (true) {
synchronized (selectorLock1) {
selector.select();
}
synchronized (selectorLock2) {}
....
}