In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-25 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >
Share
Shulou(Shulou.com)05/31 Report--
This article introduces the relevant knowledge of "how to use the netty ServerBootstrap.bind method". Many people will encounter such a dilemma in the operation of actual cases, so let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
We all know that netty is based on java nio, so specifically, how some specific elements in java nio, such as bind,selector,channel, appear in netty. Let's take a look today.
Start with the ServerBootstrap.bind () method.
The specific implementation of this method is in AbstractBootstrap, and you can see the doBind method directly.
Final ChannelFuture regFuture = initAndRegister ()
Let's see what initAndRegister is doing here.
The first step is to create a channel and assign a process from the boss group to the newly created channel.
Channel channel
Try {
Channel = createChannel ()
} catch (Throwable t) {
Return VoidChannel.INSTANCE.newFailedFuture (t)
}
Then is the initialization work, the specific content here does not delve into.
Try {
Init (channel)
} catch (Throwable t) {
Channel.unsafe () .closeForcibly ()
Return channel.newFailedFuture (t)
}
Then there is registration, and first we get a promise, which, as I understand it, is to asynchronously return the results of various operations, which we will often see later. And then execute register, and we find a very weird thing, unsafe.
This thing is brought out when creating channel, the specific function is to deal with java nio, injection bind,register and other operations, are completed in this, why to do such a thing, I don't know at present, we'll talk about it later.
ChannelPromise regFuture = channel.newPromise ()
Channel.unsafe () register (regFuture)
If (regFuture.cause ()! = null) {
If (channel.isRegistered ()) {
Channel.close ()
} else {
Channel.unsafe () .closeForcibly ()
}
}
Then there is AbstractChannel$AbstractUnsafe.register (), the first judgment is very interesting, we can understand that if the eventLoop corresponding to the current channel is already executing, that is, the current code is already in a child thread, then directly call the register0 method, otherwise, a new thread will execute.
If (eventLoop.inEventLoop ()) {
Register0 (promise)
} else {
Try {
EventLoop.execute (new Runnable () {
@ Override
Public void run () {
Register0 (promise)
}
});
} catch (Throwable t) {
Logger.warn (
"Force-closing a channel whose registration task was not accepted by an event loop: {}"
AbstractChannel.this, t)
CloseForcibly ()
CloseFuture.setClosed ()
Promise.setFailure (t)
}
}
Then let's take a look at what's going on in register0:
Try {
/ / check if the channel is still open as it could be closed in the mean time when the register
/ / call was outside of the eventLoop
If (! ensureOpen (promise)) {
Return
}
DoRegister ()
Registered = true
Promise.setSuccess ()
Pipeline.fireChannelRegistered ()
If (isActive ()) {
Pipeline.fireChannelActive ()
}
} catch (Throwable t) {
/ / Close the channel directly to avoid FD leak.
CloseForcibly ()
CloseFuture.setClosed ()
If (! promise.tryFailure (t)) {
Logger.warn (
"Tried to fail the registration promise, but it is complete already." +
"Swallowing the cause of the registration failure:", t)
}
}
First check the status of the current channel through promise, and then execute doRegister. This method is implemented in AbstractNioChannel, and the main contents are as follows:
SelectionKey = javaChannel () .register (eventLoop () .selector, 0, this)
Well, now we have identified two problems. The first selector exists in eventLoop, specifically, it should be in boss loop. The second problem is that when register is executed, bind has not been executed yet.
After that, promise is set up, and the ChannelRegistered () event is initiated through pipeline.
Let's go back to the AbstractBootstrap .doBind method. The first step, initializing and registering the selector, is complete.
Final ChannelFuture regFuture = initAndRegister ()
Final Channel channel = regFuture.channel ()
If (regFuture.cause ()! = null) {
Return regFuture
}
Final ChannelPromise promise
If (regFuture.isDone ()) {
Promise = channel.newPromise ()
DoBind0 (regFuture, channel, localAddress, promise)
} else {
/ / Registration future is almost always fulfilled already, but just in case it's not.
Promise = new DefaultChannelPromise (channel, GlobalEventExecutor.INSTANCE)
RegFuture.addListener (new ChannelFutureListener () {
@ Override
Public void operationComplete (ChannelFuture future) throws Exception {
DoBind0 (regFuture, channel, localAddress, promise)
}
});
}
How to understand the above code, especially the part after if (regFuture.isDone ()), we mentioned earlier that the specific register process may be executed in a child thread, so we need to wait for register to complete before we can proceed to the next bind operation.
Looking at the implementation of doBind0, there is still a thread directly set up to perform the bind operation.
Channel.eventLoop () .execute (new Runnable () {
@ Override
Public void run () {
If (regFuture.isSuccess ()) {
Channel.bind (localAddress, promise) .addListener (ChannelFutureListener.CLOSE_ON_FAILURE)
} else {
Promise.setFailure (regFuture.cause ())
}
}
});
Look at channel.bind, the method is implemented in AbstractChannel, it's interesting to do this bind directly through pipeline. So let's take a look at pipeline.bind. In the implementation of DefaultChannelPipeline, what we see is tail.bind, so obviously, we are going to traverse the linked list in reverse and finally execute bind through head. So let's take a look at the HeadHandler.bind method, unsafe.bind (localAddress, promise); by looking for the code, we find that unsafe is the unsafe of the Server channel that we created in the first place, which is the same thing.
Let's take a look at AbstractChannel$AbstractUnsafe 's bind method, which involves some reading and judging of the operating system information, and then calls the NioServerSocketChannel.doBind () method, where the real bind operation of java nio is executed.
The last thing is how the channel in java nio appears in netty. Quite simply, take a look at the class NioServerSocketChannel, where there is a newSocket method that directly returns a ServerSocketChannel of java.
Above, we have basically achieved the purpose of our code analysis and figured out what we did when the netty server was started.
Some specific elements of java nio are found in netty.
At the same time, we found the specific timing of two specific event,bind and channelRegistered in handler.
In addition, we have a preliminary understanding of the asynchronous return mechanism provided by netty and how ChannelFuture works.
This is the end of "how to use the netty ServerBootstrap.bind method". Thank you for reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.