Work scenario: Use Netty long connection to obtain vehicle positioning data of third-party interfaces in real time
Development environment: JDK8
Netty basic introduction
1. What is Netty
Netty is a Java open source framework provided by JBOSS, now a standalone project on Github. It is an asynchronous event-driven network application framework for rapid development of high-performance and high-reliability network IO programs. Netty is mainly aimed at high concurrent applications for Clients under the TCP protocol, or applications where large amounts of data are continuously transmitted in the Peer-to-Peer scenario.
Netty provides a complete set of APIs for handling network IO operations such as TCP and UDP sockets. It encapsulates the underlying network programming details, allowing developers to focus more on the implementation of business logic. Netty uses an efficient threading model that can handle a large number of concurrent connections and is very scalable.
Netty has a wide range of applications in many fields, such as RPC framework, gaming industry, big data field, etc. It supports a variety of transport types and protocols, such as blocking and non-blocking, UDP transport based on BIO and NIO, local transport (in-VM transport), HTTP channels, etc. At the same time, Netty also provides a rich codec for handling codec operations of various protocols.
Netty's overall structure includes the core layer and the protocol support layer. The core layer provides a common abstraction and implementation of underlying network communication, including a scalable event model, a common communication API, ByteBuf that supports zero copy, etc. The protocol support layer covers the encoding and decoding implementation of mainstream protocols, such as HTTP, SSL, Protobuf, etc.
Overall, Netty is a powerful and easy-to-use network application framework that can help developers quickly build high-performance and high-reliability network applications.
2. Netty core components
Netty's core components mainly include the following parts:
- Channels: Channel is an abstraction of Netty network communications and is used for I/O operations. It can be regarded as a basic abstraction of Java NIO, representing an open connection with hardware devices, files, network sockets and other entities, or a program that can complete I/O operations such as reading and writing. Channels can be opened or closed, connected or disconnected.
- Callbacks (callback): Callback is a method that is a reference provided to another method, so that another method can go back and call the Callback method at appropriate times. Callback is widely used in many programming situations and is one of the most commonly used methods to notify relevant parties that an operation has been completed.
- Futures: In Netty, Futures is used for the results of asynchronous I/O operations. When an asynchronous operation starts, a Future will be returned immediately, which will get a result or an exception when the operation is completed.
- Handlers: Handlers are components in Netty that handle I/O events or intercept I/O operations. Netty provides many built-in Handlers, such as ChannelInboundHandler, ChannelOutboundHandler, etc. These Handlers can handle various I/O events, such as connection establishment, data reception, exception handling, etc.
- Bootstrap vs. ServerBootstrap: Bootstrap and ServerBootstrap are boot classes of Netty programs, mainly used to configure various parameters and start the entire Netty service. They all inherit from the AbstractBootstrap abstract class. The difference is that Bootstrap is used for client booting, while ServerBootstrap is used for server booting.
- EventLoopGroup: EventLoopGroup can be understood as a thread pool used to handle I/O operations. In server programs, two EventLoopGroups are generally bound, one is used to handle Accept events (i.e., a new connection request), and the other is used to handle read and write events.
The above components together form Netty's core framework, allowing developers to focus more on the implementation of business logic without having to pay too much attention to the underlying network communication details.
3. Integration of SpringBoot and Netty
1. Add dependencies
In the SpringBoot project file, we need to add Netty's dependencies. Netty's official Maven warehouse address is: /artifact//netty-all
<dependencies> <!-- mybatis-plus --> <dependency> <groupId></groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <!-- Mysql --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- Data Source --> <dependency> <groupId></groupId> <artifactId>druid-spring-boot-starter</artifactId> </dependency> <!-- netty --> <dependency> <groupId></groupId> <artifactId>netty-all</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>commons-pool2</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <dependency> <groupId></groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>${}</version> </dependency> </dependencies>
2. Create Netty server
@Component public class NettyServer { //Responsible for handling accepted links private EventLoopGroup bossGroup; //Responsible for handling I/O operations on the already received connection private EventLoopGroup workerGroup; //In this scenario, it represents the result of the binding operation of the server private ChannelFuture future; @PostConstruct public void startServer() throws Exception { bossGroup = new NioEventLoopGroup(); workerGroup = new NioEventLoopGroup(); try { //Create ServerBootstrap, this class encapsulates the server-side network configuration, allowing us to easily set server parameters ServerBootstrap bootstrap = new ServerBootstrap(); (bossGroup, workerGroup) .channel() .childHandler(new NettyServerInitializer()); // Bind the port and start accepting incoming connections future = (7000).sync(); // Wait for the server socket to close ().closeFuture().sync(); } finally { (); (); } } @PreDestroy public void stopServer() { if (future != null && !()) { (true); } (); (); } }
Code parsing
Class annotation
-
@Component
: This is annotation of the Spring framework, indicating that this class is a component, Spring will scan to this class and register it as a bean into the Spring container. Therefore, this class can be automatically assembled by other Spring-managed beans (if needed).
Class member variables
-
bossGroup
andworkerGroup
: These two areEventLoopGroup
An instance of the process of network events.bossGroup
Mainly responsible for receiving incoming connections, andworkerGroup
Responsible for handling I/O operations on the already received connection. -
future
: This is aChannelFuture
The example of the , represents the result of an asynchronous I/O operation. In this scenario, it represents the result of the binding operation of the server.
startServer method
- This method uses
@PostConstruct
Annotation, which means that this method will be called automatically when the Spring container instantiates the bean and completes dependency injection. - In this method, two are created first
NioEventLoopGroup
Examples, one for boss and one for worker. - Then, use
ServerBootstrap
Class to configure and start the server. This class encapsulates the server-side network configuration, allowing us to easily set server parameters. - pass
group
Methods to set boss and workerEventLoopGroup
。 - pass
channel
Method Specify UseNioServerSocketChannel
Implemented as a channel for the server. - pass
childHandler
How to deal with a new connection after it is accepted. Used hereNettyServerInitializer
(This class is not defined in the provided code snippet, but we can assume that it is aChannelInitializer
Implementation for configuring newChannel
)。 - use
bind
Method binds the server to the specified port (here is 7000) and usessync
The method blocks until the binding is complete. - Finally, use
closeFuture().sync()
The method blocks the current thread until the server socket is closed. - exist
finally
In the block, it will be closed gracefully regardless of whether an exception occurs or not.EventLoopGroup
。
stopServer method
- This method uses
@PreDestroy
Annotation means that this method will be automatically called before the Spring container destroys the bean. - In this method, first check
future
Whether it has been completed (i.e. whether the server has been shut down). If not, callcancel(true)
Method to try to cancel this operation. However, it should be noted thatcancel
It may not always be possible to stop the server immediately, it is more about trying to stop the server than forcing it to stop.
3. Create a character parser to parse received messages
public class NettyServerInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel ch){ ChannelPipeline pipeline = (); // Add a string decoder to convert the received ByteBuf into a string // Assume here is using the UTF-8 character set ("decoder", new StringDecoder(CharsetUtil.UTF_8)); // Add a string encoder to convert the sent string into ByteBuf // In this way, when the server sends a string, the client can directly receive the string ("encoder", new StringEncoder(CharsetUtil.UTF_8)); // Add a custom ChannelInboundHandlerAdapter to handle business logic ("handler", new MyChannelHandler()); } }
This code defines aNettyServerInitializer
class, it inherits fromChannelInitializer<SocketChannel>
, and coveredinitChannel
method. In Netty,ChannelInitializer
It is a special processor, its main purpose is to help users configure a new oneChannel
ofChannelPipeline
. Netty will automatically call when a new connection is acceptedChannelInitializer
ofinitChannel
Method to set this new connectionChannelPipeline
。
Specifically,initChannel
The method will be called in the following cases:
- when
ServerBootstrap
ofbind
After the method is called and successfully bound to a port, it starts listening for incoming connections. - Once a client is connected to the server,
ServerBootstrap
Will accept this connection and create a new oneSocketChannel
to represent this connection. - For this new
SocketChannel
Netty will call the previously setChannelInitializer
(In this example,NettyServerInitializer
)ofinitChannel
method. -
initChannel
This new method will be configured internallySocketChannel
ofChannelPipeline
, add decoder, encoder, service processor, etc. - once
initChannel
The method has been executed, thisChannelInitializer
The mission is completed and will be completed fromChannelPipeline
remove itself because it is only responsible for initialization and does not participate in subsequent data processing.
So, in summary,NettyServerInitializer
ofinitChannel
The method will be run when a new client connection is accepted by the server and is used to initialize the new connection.ChannelPipeline
。
4. Create a Handler to process the received message
public class MyChannelHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // Process the received data here ("msg = " + msg); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // Handle exceptions here } }
4. Problems encountered during development (not yet solved)
1. After the character parser is defined, the received message is still garbled
2. After the project is started, you can access the netty port number, but the project port number cannot be accessed (solved)
// ().closeFuture().sync(); just block this code
This is the end of this article about SpringBoot integrating Netty server. For more related content related to SpringBoot integrating Netty server, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!