1. Request processing process AprEndPoint
When a request is sent to Tomcat, it is forwarded by the Connector to AprEndPoint, which calls the startInternal() method. This method does four things:
- LimitLatch Limits connection times.
- The Poller thread is created.
- The sendFile thread was created.
- An acceptor was created.
Poller, SendFile, and Acceptor are all internal classes of AprEndPoint because their parent classes implement Runnable, so the core logic is in their own run() methods.
There is so much source code involved that I just can’t be bothered to show it, so I drew the following diagram to give you an idea.
LimitLatch
Is the connection controller, which controls the maximum number of connections.Acceptor
Running in a single thread, it passes calls in an infinite loopaccept()
Method to receive a new connection, which returns a longsocket
And then put thissocket
Encapsulated intoAprSocketWrapper
Object.Poller
It also runs in a separate thread, which maintains one internallySocketList
Object that containssocket
Array, it’s checking in an infinite loopsocket
Data ready state, once there issocket
Readable, it generates oneSocketProcessor
The task object is thrown toExecutor
To deal with.Executor
It’s just a thread pool that runsSocketProcessor
The task,SocketProcessor
的run()
Method will callHttp11Processor
To read and parse the request data.
Some of your friends have no idea what AprEndPoint or Apr is after reading it.
A brief introduction:
APR (Apache Portable Runtime Libraries) is the Apache Portable Runtime library implemented in C language. It aims to provide a cross-platform operating system interface library for upper-layer applications. Tomcat can use it to handle both file and network I/O to improve performance.
In Tomcat8.5. X, the default I/O mode using the NIO, use linker is org. The apache. Coyote. Http11. Http11NioProtocol, of course, as is the default, without display configuration, In server.xml, you just need to write:
<Connector port="8080" protocol="HTTP / 1.1"
connectionTimeout="20000"
redirectPort="8443" />
Copy the code
But if you wanted to change it to APR, you would have to write it like this:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11AprProtocol"
maxThreads="150" SSLEnabled="true" >
<UpgradeProtocol className="org.apache.coyote.http2.Http2Protocol" />
<SSLHostConfig>
<Certificate certificateKeyFile="conf/localhost-rsa-key.pem"
certificateFile="conf/localhost-rsa-cert.pem"
certificateChainFile="conf/localhost-rsa-chain.pem"
type="RSA" />
</SSLHostConfig>
</Connector>
Copy the code
Now, a soul-searching question, how does APR improve performance?
Like NioEndpoint, AprEndpoint implements non-blocking I/O. The differences are: NioEndpoint implements non-blocking I/O by calling Java’s NIO API, whereas AprEndpoint implements non-blocking I/O by JNI invoking the APR native library.
The Tomcat Endpoint component needs to allocate a Buffer in advance when receiving network data. The so-called Buffer is byte array []. Java passes the address of this Buffer to C code through JNI calls. C code reads the Socket through the operating system API and populates the Buffer with data.
The Java NIO API provides two types of buffers to receive data: HeapByteBuffer and DirectByteBuffer.
The HeapByteBuffer object itself is allocated on the JVM heap, and the byte array it holds, Byte [], is allocated on the JVM heap. However, if HeapByteBuffer is used to receive network data, the data needs to be copied from the kernel to a temporary local memory and then from temporary local memory to the JVM heap, rather than directly from the kernel to the JVM heap.
As data is copied from the kernel to the JVM heap, the JVM may undergo GC, and the object may be moved during GC, which means that the byte array on the JVM heap may be moved, invalidating the Buffer address. The JVM can be guaranteed not to GC any copies from local memory to the JVM heap if there is a local memory transfer.
Tomcat’s AprEndpoint solves this problem with the sendFile feature at the operating system level, which is very concise.
2. Request processing process NioEndPoint
In the context of AprEndpoint’s request processing, let’s take a look at Tomcat’s default NioEndPoint processing.
In fact, the two processes are very similar, and the difference is basically the implementation of non-blocking I/O.
- in
Acceptor
In theaccept()
Method returns aChannel
Object, go aheadChannel
Object toPoller
To deal with. Poller
Maintain one internallyChannel
Array, it’s checking in an infinite loopChannel
Data ready state, once there isChannel
Readable, it generates oneSocketProcessor
The task object is thrown toExecutor
To deal with. eachPoller
Threads have their ownQueue
. eachPoller
Threads can be multiple at the same timeAcceptor
Thread calls to registerPollerEvent
。Poller
Constantly through the internalSelector
Object queries to the kernelChannel
Once readable, the task class is generatedSocketProcessor
toExecutor
To deal with.Poller
Another important task is to iterate over what you manageSocketChannel
If it’s timed out, if it’s timed out, turn this offSocketChannel
。Executor
Is the thread pool, which is responsible for runningSocketProcessor
The task,SocketProcessor
的run()
Method will callHttp11Processor
To read and parse the request data.ServerSocketChannel
throughaccept()
Accept new connections,accept()
Method return getSocketChannel
Object, and then willSocketChannel
The object is encapsulated in onePollerEvent
Object, and willPollerEvent
Press the object intoPoller
的Queue
It’s a classic producer-consumer model,Acceptor
与Poller
Thread to thread passQueue
Communication.
reference
Jonhuster.blog.csdn.net/article/det…
This article is constantly updated, you can search “Geek excavator” on wechat to read it in the first time, and the key words in reply have all kinds of tutorials PREPARED by me, welcome to read.