Important concepts
Channel
channel is one of the core concepts of Netty. It is the main body of Netty network communication. It is responsible for network communication, registration and data operation with the opposite end.
Every time Netty establishes a connection, there will be a corresponding channel instance, and there is the concept of parent-child channel. The channel monitored by the server connection is also called parent channel. The channel corresponding to each Socket connection, also known as child channel.
In the server, there are usually two thread groups. The parent channel connected by the listener works in an independent thread group, while the child channel established after the client connection is successful works in another thread group.
Type of channel
- NioSocketChannel represents an asynchronous client TCP Socket connection
- NioServerSocketChannel, Asynchronous Server - side TCP Socket connection
- NioDatagramChannel, asynchronous UDP connection
- NioSctpChannel, asynchronous client Sctp connection
- Niosctp server channel, asynchronous Sctp server-side connection
- OioSocketChannel, a synchronous client TCP Socket connection
- OioServerSocketChannel, a synchronous server - side TCP Socket connection
- Oodatagramchannel, synchronous UDP connection
- Oosctp channel, synchronous Sctp server-side connection
- Oosctpserverchannel, synchronous client TCP Socket connection
EventLoop
Multiple channels can be registered on an eventloop, and all operations are performed sequentially. eventloop will call channel methods for related operations according to channel events. The operations and processing of each channel are sequential in eventloop.
In Netty, each channel is bound with a thread thread.
A thread thread is encapsulated into one EventLoop and multiple eventloops to form a thread group EventLoopGroup.
EventLoop is equivalent to a processing thread. It is the thread that Netty receives requests and processes IO requests. EventLoopGroup can be understood as a class for grouping and managing multiple eventloops. It is a group of eventloops.
Bootstrap
Bootstrap is a factory class officially provided by Netty. Bootstrap can be used to initialize Netty client or server simply and quickly. If you do not use this initiator, you need to manually create channel s and other settings and startup, which is more complex and difficult.
There are two kinds of Bootstrap: Bootstrap (client specific) and ServerBootstrap (server specific). Both of them inherit AbstractBootstrap.
Bootstrap process
[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-log5klkr-1642490912772) (netty% E4% B8% ad% E7% 9A% 84% E5% 9F% Ba% E6% 9C% AC% E6% A6% 82% E5% BF% b5_md_files / image_20220118123929. PNG? V = 1 & type = image & token = V1: hxuzqtdfjhmrha2stv0d83e1ead gnjlzfqu7eqy2da)]
First, create a Bootstrap instance:
ServerBootstrap b = new ServerBootstrap(); //There are also two thread groups declared for creating Reactor thread groups EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup();
-
bossLoopGroup refers to the server connection listening thread group, which specifically accepts new client connections
-
workerGroup refers to the thread group that handles the data sending and receiving of each connection
Then set the Reactor thread group
(for Reactor mode, please refer to this article: https://www.jianshu.com/p/eef7ebe28673 )
b.group(bossGroup, workerGroup) //You can also set only one thread group instead of two thread groups. //If only one thread group is set, the specific method is b.group( workerGroup)
After configuring a thread group, all channels, including the service listening channel, the parent channel and all child channels, work in the same thread group.
Sets the IO type of the channel
Netty supports multi clock IO mode. NIO is configured here because NIO usually has better performance advantages.
Note: BIO in Netty is called OIO
b.channel(NioServerSocketChannel.class)
Set channel parameters
// TCP turns on the Nagle algorithm by default. The function of this algorithm is to send big data as fast as possible and reduce network transmission. TCP_ The nodelay parameter controls whether the Nagle algorithm is enabled. b.childOption(ChannelOption.TCP_NODELAY, true) // Whether to enable TCP underlying heartbeat mechanism b.childOption(ChannelOption.SO_KEEPALIVE, true) //Indicates the maximum length of the queue used by the system to temporarily store requests that have completed three handshakes. If connections are established frequently and the server is slow to process and create new connections, you can increase this parameter appropriately b.option(ChannelOption.SO_BACKLOG, 128)
childOption and option are used here. The difference between them is:
childOption is to set the child channel;
option is to set the parent channel.
About option parameters
SO_RCVBUF ,SO_SNDBUF set up TCP Two connected buffer Size. SO_SNDBUF: TCP The upper limit of the sending buffer capacity; SO_RCVBUF: TCP The maximum capacity of the accept buffer; each TCP socket There is a send buffer and a receive buffer in the kernel, TCP Full duplex working mode and TCP Sliding window for It depends on these two independent buffer And this buffer Fill status of the.
TCP_NODELAY TCP Parameter to send data immediately. The default value is Ture(Netty Default to True The operating system defaults to False). This value is set Nagle When the algorithm is enabled, the algorithm is changed to connect small pieces of data into larger messages to minimize the number of messages sent If some small messages need to be sent, the algorithm needs to be disabled. Netty The algorithm is disabled by default to minimize message transmission Input delay. Nagle:The algorithm requires one TCP There can only be one unacknowledged small packet on the connection at most. When the confirmation of the small packet arrives Other small packets cannot be sent before. This parameter is related to whether it is enabled or not Nagle The algorithm is the opposite, true Means closed, false Indicates on.
SO_KEEPALIVE For connection oriented TCP socket,In practical applications, it is usually necessary to detect whether the opposite end is connected,There are two types of connection ports condition: 1,Connection closed normally,call close() shutdown()The connection closes gracefully,send And recv Return error immediately,select return SOCK_ERR; 2,The opposite end of the connection is abnormally closed,For example, the network is broken,Sudden power failure. For the second case,There are several ways to judge whether the connection is disconnected: 1,Write your own heartbeat package,Simply put, add a thread to your program,Send data packets to the opposite end regularly,See if have ACK,according to ACK To manage the connection. This method is more general,Business layer heartbeat processing is generally used,Flexible and controllable,but Changed the existing protocol; 2,use TCP of keepalive mechanism,UNIX Network programming is not recommended SO_KEEPALIVE To do a heartbeat test. bottom TCP Heartbeat mechanism of the protocol. Socket Parameter, keep the connection alive, the default value is False. When this feature is enabled, TCP Will take the initiative Detect the validity of idle connections. You can think of this function as TCP Note that the default heartbeat interval is 7200s That is, 2 hours. Netty This function is turned off by default.
SO_REUSEADDR When two socket of address and port Conflict, and you want to reuse the address and port, the old one socket And new socket It must have been set SO_REUSEADDR characteristic Socket Parameter, address multiplexing, default value False. The following can be used: (1)When there is a with the same local address and port socket1 be in TIME_WAIT State, and you want to start the program socket2 To occupy the address and port, for example, restart the service and keep the previous port.
SO_LINGER Simply put SO_LINGER Option is used to set the time to delay closing and wait for the data in the socket send buffer to be sent Yes. When this option is not set, the close()After sending, after FIN Some cleaning work will be carried out immediately and returned. If Set SO_LINGER Option, and the wait time is positive, it will wait for some time before cleaning up.
SO_BACKLOG Socket Parameter, the length of the queue for the server to accept connections. If the queue is full, the client connection will be rejected. Default value, Windows Is 200, others are 128. Indicates the maximum length of the queue used by the system to temporarily store requests that have completed three handshakes. If the connection is established frequently, the server will process it It is slow to create a new connection. You can increase this parameter appropriately.
SO_BROADCAST Socket Parameter to set the broadcast mode.
Assembly flow
b.childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) { ch.pipeline().addLast(new NettyKryoDecoder(kryoSerializer, RpcRequest.class)); ch.pipeline().addLast(new NettyKryoEncoder(kryoSerializer, RpcResponse.class)); ch.pipeline().addLast(new NettyServerHandler()); }
ChannelPipeline is the responsibility chain for Netty to process requests. It is a linked list of ChannelHandler, which is used to process the contents of network requests.
Each channel has a processor pipeline. Assemble the child channel pipeline, call the childHandler() method, and pass an instance of ChannelInitializer.
When the child channel is created successfully and channel initialization is started, the ChannelInitializer instance configured in the bootstrap initiator will be called.
At this time, the initChannel initialization method is really executed to start the channel pipeline assembly.
Pipeline assembly is mainly to add a handler responsible for data reading, writing and processing business logic behind the pipeline.
Bind Server and port
// Binding port, blocking, waiting for successful binding ChannelFuture f = b.bind(port).sync();
Futrue multithreading
// Wait for the server listening port to close f.channel().closeFuture().sync();
ChannelFuture's methods in Netty are called asynchronously, so a ChannelFuture instance is required to obtain the Current IO status. When IO returns, the channel closes.
Close EventLoopGroup and recycle resources
finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); }
Close all child channel s and release underlying resources, such as TCP Socket file descriptors, etc.
Due to lack of talent and learning, it is inevitable that there are mistakes and omissions. I hope you will give me your advice.
For reprint of this article, please indicate: https://blog.csdn.net/elapse_/article/details/122561174
Reference
Netty learning 4: https://www.cnblogs.com/TomSnail/p/6192885.html
Netty Bootstrap: https://www.cnblogs.com/crazymakercircle/p/9998643.html