"Dry Netty", what needs to be considered when writing a low-level communication framework?

Hello everyone, my name is yes.

The Netty series was originally going to be written before Double Eleven... It has been dragged to the present, this time no pigeons! The purpose of this series is very simple, just want to understand Netty in an all-round way and contribute to our resume~ .

To this end, I have paved a few articles:

This is the beginning of the Netty series. The beginning will not go into details soon. The beginning needs to start from a high latitude and get an overview of the overall situation .

I have a habit. When I learn a new framework, I will close my eyes and think about the core points that the framework should need when I have a certain foundation.

Taking Netty as an example, I would assume that the boss gave me a task and asked me to write a low-level communication framework. How should I write it? What aspects need to be considered ?

Through this kind of driven self-questioning, you can push yourself to think and let your brain turn passively! This will make you understand more deeply.

Let's think about this together.

What do you need to consider when writing a low-level communication framework?

Regarding communication, the first thing that comes to my mind is network protocols. Fortunately, the bottom layers of some protocols have already been implemented for us, but communication still cannot avoid dealing with the bottom layers. For example, to call the interface of the operating system to send data to the remote, if we want to implement it, we have to understand the various interfaces of the operating system, which is a bit troublesome.

But fortunately, such a low-level interaction, as a language, must have provided encapsulation, and provided NIO for Java.

Therefore, some basic operations of communication, including creating sockets, establishing connections, sending messages, receiving messages, etc., are provided by NIO.

Wouldn't that just use Java NIO directly?

It must be used, but the interface provided by this language class library needs to give the upper layer more free configuration , that is, it can provide refined calls, but it is too complicated for normal use.

Just like the picture below, it may be excellent for professionals who have been deeply involved.

But for ordinary users, the cost of getting started is too high. In short, the encapsulation is not perfect and simple enough.

What we pursue is that the dashboard only needs to expose a few keys, and the application can run successfully by pressing a few keys, so we need to encapsulate based on Java NIO, hide some complex configurations, and expose a more easy-to-use interface to the outside world. .

Therefore, our first goal has been clarified, using the capabilities provided by Java NIO and encapsulating it based on it, simplifying the configuration as much as possible, and making it easy to use. (In fact, the framework is like this, such as Mybatis, etc., it still has to be based on the ability of JDBC and encapsulated on it)

The general goal is there, and then the functionality needs to be enriched.

Since network communication is byte stream, we also need to provide support for encoding and decoding, and we need to support various protocols. After all, as a framework, it needs to be used by various teams, and the communication protocols involved in each team may be different. Therefore, the framework needs to support common protocols on the market as much as possible, such as HTTP, DNS, etc., of course, it is also convenient to customize custom protocols.

By the way, you also need to consider issues such as sticking and unpacking, support for separator segmentation, fixed length, etc., giving "customers" more convenient choices!

To achieve the above, some basic communication requirements are met, and then consider performance.

As a network communication framework, we need to consider connection management. After all, resources are limited, so a reasonable number of connections is very important. Therefore, we need to provide functions such as heartbeat and checking idle connections to manage connections.

There is also the I/O model. Now this "market" is not mentioned, and it is directly multiplexed, processing more requests with fewer threads, and holding a large number of connections. Wait until Linux fully supports AIO and then go to AIO, but Linux provides epoll, so if the service is running on Linux, use epoll, otherwise use select.

By the way, zero-copy is often mentioned on the Internet. This is definitely necessary. For example, when sending some files, use zero-copy directly to reduce the number of copies, and you can also use DirectBuffer to place data outside the heap, eliminating the need for a time inside and outside the heap. Copy to improve performance.

Of course, the corresponding memory management needs to be done well. I think you can refer to the Linux partner system for this.

Regarding the thread model, it is also necessary to study and study, such as the arrangement of accept threads, reactor threads (I/O threads) and business processing threads, etc. A reasonable thread model under large traffic will reduce the number of thread switching and improve performance, which is very important .

Then a framework needs to be easy to use, not only to adapt to the different needs of different teams, but also to easily adapt to changes in the needs of the same team. This requires the framework to provide very convenient customization and plug-in functions. How should this be designed? The chain of responsibility model is suitable for this, and it seems to be perfect with event-driven.

I personally think that as a framework that provides many out-of-the-box functions, easy-to-use interfaces, good performance, and easy expansion, it is simply perfect!

In short, the thinking of the communication framework can start from the function: configure the startup service, establish a connection, receive data, process business, send data, close the connection, and close the service. Starting from this main line, consider the above-mentioned, easy-to-use interface, I/O model, codec, out-of-the-box protocol support, thread model, connection management, memory management, etc.

To sum up, these are some core points that I personally think to think about to implement a low-level communication framework. Of course, there are many details and some icing on the cake functions, which have to be carefully discussed.

It can be seen that it is not so simple to make a communication framework, there are many things to consider, which is why so many middleware underlying communication frameworks do not implement themselves, but use Netty.

Because Netty implements it all.

What is Netty?

It is the underlying framework for high-performance Java network communication. It may be used by many middleware underlying communication frameworks you have heard, such as RocketMQ, Dubbo, Elasticsearch, Cassandra, etc.

Why is it so popular? Why are so many middleware built on top of it?

easy to use

The NIO of Java is encapsulated, which shields the complexity of the use of NIO and simplifies the development of network communication.

And supports many protocols, not only HTTP, HTTP2, DNS, Redis protocol and so on.

Network programming needs to consider the problem of sticking and unpacking, connection management, codec processing, Netty is customized for you, out of the box.

It also provides advanced functions such as memory leak detection, IP filtering, and traffic shaping.

performance

Good I/O model.

Netty implements I/O multiplexing based on Java NIO encapsulation. Multiple underlying channels can be polled by one thread, which reduces thread resources and the overhead caused by multi-thread switching. It can better handle massive connections and improve system performance.

A better epoll model is also used in the Linux environment.

Use zero-copy technology. It not only utilizes the zero copy provided by the operating system, but also saves a copy between inside and outside the JVM heap based on off-heap memory.

Object pool technology, through the reuse of objects, avoids the overhead caused by frequent creation and destruction.

Extensibility

Based on the event-driven model, the business implementation is separated into ChannelHandlers, and the chain of responsibility model can be used to expand according to different businesses. Users only need to implement the relevant ChannelHandlers, and the framework is isolated from the business .

The threading model can be configured according to the situation, such as master-slave Reactor, master-multiple-slave Reactor, and so on.

At last

This article is just to talk about the core points that need to be included in the implementation of a low-level network communication framework from a high latitude, as well as a very rough overview of Netty. After the series is over, I will give a detailed overall summary.

In the next article, start to overview some of the core components of Netty.

In this Netty series, after we finish learning together, I believe that Netty may be a bonus for your future interviews, because it not only covers a wide range of knowledge, but also has many exquisite designs.


I'm yes, from a little to a million, see you in the next part~

Guess you like

Origin blog.csdn.net/yessimida/article/details/120882204