MINA Workflow

 

Many execution steps in Mina use multithreading to improve performance. Threads are used by default in three places in Mina:

 

 

 


(1.) IoAcceptor:
This place is used to accept the connection establishment of the client. Each time a port is monitored (each time the bind() method is called), a thread is enabled. We cannot change this number. This thread listens to a port for incoming requests, and once found, creates an IoSession object. Because this action is fast, one thread is enough.

 

 

 

(2.) IoConnector:
This place is used to establish a connection with the server. Each time a server is connected (each time the connect() method is called), a thread is enabled, and we cannot change it. Likewise, this thread listens for a connection to be established, and once found, creates an IoSession object. Because this action is fast, one thread is enough.

 

 

 

(3.) IoProcessor:
This place is used to perform real IO operations. The number of threads enabled by default is the number of CPU cores + 1. For example, for a single-CPU dual-core computer, the default IoProcessor thread will create 3 threads. This means that an IoAcceptor or IoConnector will be associated with an IoProcessor pool by default, and there are 3 IoProcessors in this pool. Because IO operations consume resources, the IoProcessor pool is used here to complete the read and write operations of data, which helps to improve performance. This is why the IoAccetor and IoConnector mentioned earlier use a Selector, while IoProcessor uses its own separate Selector.

 


So why is the number of IoProcessors in the IoProcessor pool only 1 larger than the number of CPU cores? Because IO read and write operations are CPU-intensive operations, and each CPU core can only run one thread at the same time, the number of IoProcessors in the IoProcessor pool is not as good as possible. The number of this IoProcessor can be adjusted as follows:

 


IoAcceptor acceptor=new NioSocketAcceptor(5);
IoConnector connector=new NioSocketConnector(5);

 

 

 

This will change the number of IoProcessor pools to 5, which means that 5 read and write operations can be processed at the same time. Remember that Mina's decoder uses IoSession to save state variables, not the Decoder itself, because Mina does not guarantee that every time the doDecode() method is executed, the same IoProcessor is used? In fact, the root cause of this problem is that the IoProcessor is a pool. Every time the IoSession enters the idle state (no data is read), the IoProcessor will be recycled into the pool for use by other IoSessions, so when the IoSession enters the busy state from the idle state again In the state, the IoProcessor will be assigned to an IoProcessor instance again, and at this time there is no guarantee that it is the same IoProcessor that was in the last busy state. You will also find that IoAcceptor and IoConnector also have a constructor. You can specify a java.util.concurrent.Executor class as a thread pool object. What is the purpose of this thread pool object? In fact, it is used to create the thread used in (1.) and (2.) to monitor whether there is a TCP connection established. By default, the Executors.newCachedThreadPool() method is used to create an Executor instance, which is an unbounded thread pool. (For details, please refer to the concurrent library of JAVA). Don't try to change the instance of this Executor, that is, use the built-in one, otherwise it may cause some inexplicable problems, such as: the performance drops suddenly at a certain traffic level. Because the unbounded thread pool is how many Sockets are established, how many threads are allocated. If you change to other methods of creating thread pools in Executors and create a bounded thread pool, then some requests will not be responded in time, resulting in some question.

 

 

 


Below we give a complete overview of Mina's workflow :

 

(1.) When an IoService instance is created, an IoProcessor pool and thread pool associated with the IoService are also created;

 

 

 

(2.) When IoService establishes a socket (IoAcceptor's bind() or IoConnector's connect() method is called), IoService takes out a thread from the thread pool and listens to the socket port;

 

 

 

(3.) When IoService listens to a connection request on the socket, it establishes an IoSession object, and takes an IoProcessor instance from the IoProcessor pool to execute the filter and IoHandler on the session channel;

 

 

 

(4.) When the IoSession channel enters the idle state or is closed, the IoProcessor is recycled.

 

 

The above is the default thread working mode of Mina, so what we are going to talk about here is how to configure the multi-threaded working mode of IoProcessor. Because an IoProcessor is responsible for executing all filters and IoHandlers on a session, that is, for IO read and write operations, it is a single-threaded way of working (that is, executed one by one in order). If you want an event method (such as sessionIdle(), sessionOpened(), etc.) to run in a separate thread (that is, the thread where the IoProcessor is not located), then you need to use an ExecutorFilter filter here. You can see that one of the parameters in the constructor of IoProcessor is java.util.concurrent.Executor, that is, the filters called by IoProcessor and some event methods in IoHandler run independently on the threads allocated in the thread pool, and Not running on the same thread as the IoProcessor.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326759179&siteId=291194637