In the use of Mina, the thread pool configuration is a more critical link, and it is also an effective way to improve the performance of Mina, in more than 2.0 versions of Mina no longer need the configuration of the Mina thread pool, this series of articles are based on the current stable version Mina In the 1.1.7 version, the 2.0 version of Mina is still in the M (Millestone, Milestone) version, in the 1.5 version of the 2.0M version of the stable version, but in 1.5+ above is an unstable version, so for better discussion and study, or based on Mina 1.1.7 version of the discussion, if you use the development of Mina 2.0 to pay attention to the JDK version of the problem, of course, if you can also modify and compile the 2.0 version of Mina, this is no longer said here, the use of the 2.0 version of the students can not ignore the content of this article.
The above content is based on the documentation provided by the Apache Mina, if necessary, please find the relevant information, no longer repeat.
The following is a brief explanation of the rationale for the configuration, use, and Excutorfilter of the Mina threading model.
three worker threads configured for Mina
There are three I/O worker threads in Mina's NiO mode (these three threading models are valid only in NIO sockets, not in NIO packets and virtual pipes, and do not need to be configured):
Acceptor thread
The purpose of this thread is to receive a connection from the client and import the client's connection into the I/O processor threading model. The so-called I/O processor threading model is Mina's I/O processor thread. Acceptor thread starts after the Acceptor.bind () method is invoked. Each acceptor can only create one acceptor thread, which cannot be configured, and it is provided by Mina itself.
Connector thread
The threading model is the client's connection threading model, which, like acceptor thread, imports the client-server connection into the I/O processor threading model. Similarly, the threading model was created automatically by Mina's client, and the threading model could not be configured.
I/O processor thread
The main role of the threading model is to receive and send data on the line, all IO operations after the server and the client connection is established, all the data received and sent by the thread model to be responsible, know that the client and the server connection shutdown, the threading model to stop working. The threading model can be configured by the programmer as needed. The number of default threads for this threading model is +1 of the CPU's kernel. If your CPU is dual core, then your I/O processor thread Maximum number is 3, similarly if your CPU is four cores, then your I/O processor the maximum number of threads is 5.
We know from the above that the number of threads that can be configured in Mina is only I/O processor, and you can configure the Ioservice I/O processor threads for each ioservice to create an instance of it. The number of I/O processor in Sokcetconnector and Socketaccpetor is determined by the CPU's kernel number of +1.
They are configured as follows: Java code <span><span style= "Font-size: small" > /*** * Configure the number of i/o processor threads for the Socketacceptor listener, * The number of i/o processor threads here is determined by the CPU's kernel, but acceptor There is only one thread number for * , that is, there is only one number of threads receiving client connections, * The number of acceptor threads cannot be configured. * */ socketacceptor acceptor = new socketacceptor (Runtime.getRuntime () . Availableprocessors () + 1, executors.newcachedthreadpool ()); /*** * Configure the number of i/o processor threads for the Socketconnector listener, * The number of i/o processor threads here is determined by the CPU's kernel, but socketconnector There is only one thread number for * , that is, there is only one number of threads receiving client connections, * The number of socketconnector threads cannot be configured. * */ socketconnector connector = new socketconnector (Runtime.getRuntime () . Availableprocessors () + 1, executors.newcachedthreadpool ()); </SPAN></SPAN>
/*** * Configure the number of I/O processor threads for socketacceptor listeners, * The number of I/O processor threads here is determined by the CPU's kernel number
Decision, but the number of threads acceptor * is only one, that is, there is only one number of threads receiving client connections, * the number of acceptor threads cannot be configured. * */Socketacceptor acceptor = new Socketacceptor (Runtime.getruntime (). Availableprocessors () + 1,
Executors.newcachedthreadpool ());
/*** * The number of threads that configure the Socketconnector listener's I/O processor, * The number of I/O processor threads here is determined by the CPU's audit, but Socketconnector
* The number of threads is only one, that is, the number of threads that receive client connections is only one, * the number of socketconnector threads cannot be configured. * */Socketconnector connector = new Socketconnector (Runtime.getruntime (). Availableprocessors () +
1, Executors.newcachedthreadpool ());
What is more difficult to understand in the above configuration is Runtime.getruntime (). Availableprocessors () + 1, which means that the JVM determines the number of IO processor threads based on the system's situation (that is, the kernel number of CPUs). Although the number of this thread is in the Socketacceptor/socketconnector constructor, it has no effect on Socketacceptor/socketconnector's own threads, Socketacceptor/ The number of threads in the Socketconnector is still 1. The socketacceptor/socketconnector itself encapsulates IO processor,socketacceptor/socketconnector only a separate thread is responsible for receiving external connections/establishing connections to external requests, When the connection is established, Socketacceptor/socketconnector transfers the data sent and received to the I/O processor thread. This can be seen in the illustrations in the Iofilter and Iohandler differences and connections in this series of articles.
The figure clearly shows that IO processor is located between Ioservice and Iofilter, Ioservice responsible for and external connection, while iofilter is responsible for processing received data, Ioprocessor is responsible for the data receiving and dispatching work.
About the number of threads that configure IO processor There is also a more "stupid" approach, that one test, you can according to your PC hardware situation starting from 1, each time add 1, and then get IO processor The number of the best threads. But this way personal advice is best not to use, the above method is sufficient. The configuration method is as follows: Java code <span><span style= "Font-size:small" >//starting from 1--n, the maximum number of n is CPU kernel +1 socketacceptor acceptor = n EW Socketacceptor (N, Executors.newcachedthreadpool ()); </SPAN></SPAN>
Starting from 1--n, the maximum number of N is the CPU kernel number +1
socketacceptor acceptor = new Socketacceptor (n, Executors.newcachedthreadpool ());
add a thread pool to Mina's Iofilterchain
A executorfilter is provided in the Mina API, which implements the Iofilter interface, which can be added as a iofilter to the Iofilterchain, which is the function of the I/O Events in the processor are forwarded to the next filter through a line pool its own encapsulation. When the threading model is not added, an I/O processor event is triggered by a method and then forwarded to Iohandler. When the thread pool is not added, all events are run in single-threaded mode, meaning that some events and processes (IO processor,iohandler,iofilter) are running on the same thread, which is the IO Processor thread, However, the number of this thread is affected by the number of CPU cores, so the performance of the system is directly affected by the CPU kernel number.
More complex applications generally use this thread pool, you can according to your needs in the iofilterchain you can add any number of thread pools, these thread pools can be combined into an event-driven (SEDA) processing model. For general applications, the more the number of threads is, the better. The greater the number of threads may exacerbate the time spent by the CPU switching threads, but the performance of the system, so the number of threads needs to be added incrementally, depending on the actual need, to find the number of threads that are best suited to your system. The Excutorfilter configuration process is as follows: Java code <span><span style= "Font-size:small" >socketacceptor acceptor = ...; Defaultiofilterchainbuilder Filterchainbuilder = Acceptor.getdefaultconfig (). Getfilterchain (); Filterchainbuilder.addlast ("ThreadPool", New Executorfilter (Executors.newcachedthreadpool ()); </SPAN></SPAN>
Socketacceptor acceptor = ...;
Defaultiofilterchainbuilder Filterchainbuilder = Acceptor.getdefaultconfig (). Getfilterchain ();
Filterchainbuilder.addlast ("ThreadPool", New Executorfilter (Executors.newcachedthreadpool ());
One issue to note when configuring the thread pool is that when you use a custom protocolcodecfactory, be sure to configure the thread pool behind the filter, as follows: Java code <span><span style= " Font-size:small ">defaultiofilterchainbuilder Filterchainbuilder = Acceptor.getdefaultconfig (). GetFilterChain () ; and CPU-bound operations are configured in front of the filter Filterchainbuilder.addlast ("Codec", new Protocolcodecfactory (...)); Add thread pool Filterchainbuilder.addlast ("ThreadPool", New Executorfilter (Executors.newcachedthreadpool ()); </SPAN></SPAN>
Defaultiofilterchainbuilder Filterchainbuilder = Acceptor.getdefaultconfig (). Getfilterchain ();
and CPU-bound operations are configured in front of the filter
filterchainbuilder.addlast ("Codec", new Protocolcodecfactory (...));
Add thread pool
filterchainbuilder.addlast ("ThreadPool", New Executorfilter (Executors.newcachedthreadpool ());
Because the protocolcodecfactory you implement directly reads and converts binary data, which are read and sent by the CPU-bound I/O processor, so you should bind the codec operation of the data to I/O without affecting the performance of the system. Processor threads, because creating and threading in Java is more resource-intensive, it is recommended that Protocolcodecfactory be configured in front of Executorfilter. A detailed account of protocolcodecfactory will be given in a subsequent document, not to mention here.
Finally, we give an example of a complete configuration of the server threading model, which is configured with Kfcclient, with the detailed code in the attachment, giving only the main part of the code: Java code <span><span style= "Font-size: small" >socketaddress address = new inetsocketaddress ("localhost", 4321); /*** * Configure the number of i/o processor threads for socketacceptor listeners, here I/o The number of threads in the * processor is determined by the CPU's kernel count, but there is only one acceptor number of threads, that is, the number of threads receiving client connections is only one , the number of threads * acceptor cannot be configured. * */ ioacceptor acceptor = new socketacceptor (Runtime.getRuntime () . Availableprocessors () + 1, executors.newcachedthreadpool ()); acceptor.getdefaultconfig (). Setthreadmodel (threadmodel.manual); // codec for configuration data acceptor.getdefaultconfig (). Getfilterchain (). AddLast ("Codec", new Protocolcodecfilter (New objectserializationcodecfactory ())); // here for your own implementation of codec // config.getfilterchain (). AddLast ("Codec", new // protocolcodecfactory (...)); // for IOFIlterchain add thread pool acceptor.getdefaultconfig (). Getfilterchain (). AddLast ("ThreadPool", new executorfilter (Executors.newcachedthreadpool ())); acceptor.getdefaultconfig (). Getfilterchain (). AddLast ("Logger", new loggingfilter ()); // Binding server ports acceptor.bind (Address, new kfcfoodpricehandler ()); system.out.println (" server started in 8000 Port monitoring ... "); // ==========================================// // i/o for clients here Processor thread number configuration, you can imitate // // Ioacceptor configuration to implement // // =================== =======================// /*** * Configure the number of i/o processor threads for socketconnector listeners, here I/O The number of threads * processor is determined by the CPU's kernel, but socketconnector The number of threads * is only one, that is, the number of threads receiving client connections is only one, The number of Socketconnector threads cannot be configured. * */ // socketconnector connector = new socketconnector ( Runtime.getruntime () // .availableprocessors () + 1, executors.newcachedthreadpool ()); } </SPAN></SPAN><SPAN><SPAN Style= "Font-size: small" > </SPAN></SPAN>