Socket Communication for Tomcat source code analysis
All articles in this series are Tomcat 7.0 code analysis.
1. socket communication:
Tomcat can handle sockets in the following ways:
- Bio method: use Java to block socket communication.
- NIO method: Previously, bio (blocking method) was used. Now, NiO is introduced after java1.4 to provide NiO implementation.
- APR: for better integration with local machines and higher performance, such as some advanced system Io functions (sendfile, epoll and OpenSSL) and Local Operation Processing (shared memory, NT pipes and Unix sockets and OS level functions (Random Number Generation, system status, etc). Tomcat uses JNI to call and process socket links.
- The combination of AJP and ARP.
- AJP mode: communication through the AJP Protocol: AJP is mainly used for communication between the HTTP server of Apache and the servlet Web container. It is packet_oriented, in other words, it is sent to the browser (other Web servers) the data is packet (s), and the response from the servlet container is packet (s). In this case, if the data sent by the servlet container is binary, it is directly sent to the browser. In addition, AJP can reuse the socket connection between servlet containers to reduce the creation overhead. For details, see http://httpd.apache.org/docs/2.2/mod/mod_proxy_ajp.html.
2. Model Introduction
Connector consists of protocolhandler and a connection port. protocolhandler uses the methods described above to process sockets.
The code for selecting different protocolhandler implementation classes based on the configuration is as follows:
Java code
- /**
- * Set the coyote protocol which will be used by the connector.
- *
- * @ Param Protocol the coyote protocol name
- */
- Public void setprotocol (string protocol ){
- If (aprlifecyclelistener. isapravailable ()){
- If ("HTTP/1.1". Equals (Protocol )){
- Setprotocolhandlerclassname
- ("Org. Apache. Coyote. http11.http11aprprotocol ");
- } Else if ("AJP/1.3". Equals (Protocol )){
- Setprotocolhandlerclassname
- ("Org. Apache. Coyote. AJP. ajpaprprotocol ");
- } Else if (protocol! = NULL ){
- Setprotocolhandlerclassname (Protocol );
- } Else {
- Setprotocolhandlerclassname
- ("Org. Apache. Coyote. http11.http11aprprotocol ");
- }
- } Else {
- If ("HTTP/1.1". Equals (Protocol )){
- Setprotocolhandlerclassname
- ("Org. Apache. Coyote. http11.http11protocol ");
- } Else if ("AJP/1.3". Equals (Protocol )){
- Setprotocolhandlerclassname
- ("Org. Apache. Coyote. AJP. ajpprotocol ");
- } Else if (protocol! = NULL ){
- Setprotocolhandlerclassname (Protocol );
- }
- }
- }
The corresponding configuration example is as follows:
Java code
- <Connector Port = "8080" protocol = "HTTP/1.1"
- Connectiontimeout = "20000"
- Redirectport = "8443" type = "regxph" text = "yourobjectname"/>
Connector calls the protocolhandler object to process the socket. The main code is in startinternal () of the connector class, as follows:
Java code
- /**
- * Begin processing requests via this connector.
- *
- * @ Exception lifecycleexception if a fatal startup error occurs
- */
- @ Override
- Protected void startinternal () throws lifecycleexception {
- Setstate (lifecyclestate. Starting );
- Try {
- Protocolhandler. Start ();
- } Catch (exception e ){
- String errprefix = "";
- If (this. Service! = NULL ){
- Errprefix + = "service. getname (): \" "+ this. Service. getname () + "\";";
- }
- Throw new lifecycleexception
- (Errprefix + "" + SM. getstring
- ("Coyoteconnector. protocolhandlerstartfailed"), e );
- }
- Mapperlistener. Start ();
- }
The protocolhandler object starts a corresponding abstractendpoint object to create a serversocket, listen to the corresponding port of the service, and start the thread pool to process messages.
The code for the protocolhandler object to start the abstractendpoint object is in the org. Apache. Coyote. abstractprotocolhandler class, as follows:
Java code
- @ Override
- Public void start () throws exception {
- If (getlog (). isinfoenabled ())
- Getlog (). Info (Sm. getstring ("abstractprotocolhandler. Start ",
- Getname ()));
- Try {
- Endpoint. Start ();
- } Catch (exception ex ){
- Getlog (). Error (Sm. getstring ("abstractprotocolhandler. starterror ",
- Getname (), Ex );
- Throw ex;
- }
- }
The abstractendpoint corresponding to different protocolhandler is as follows:
Protocolhandler |
Abstractendpoint |
Ajpaprprotocol |
Aprendpoint |
Ajpprotocol |
Jioendpoint |
Http11aprprotocol |
Aprendpoint |
Http11nioprotocol |
Nioendpoint |
Http11protocol |
Jioendpoint |
See the implementation of this class for different protocol processing methods: aprendpoint, jioendpoint, and nioendpoint.
Jioendpoint adopts bio processing and nioendpoint adopts NiO processing. aprendpoint calls a large number of native methods of poll to process sockets. I will not introduce them one by one.
Finally, we draw a simple model for the three components, as shown below:
3. Relationship between server, service, and connector in Tomcat:
A server contains multiple services, and a service consists of multiple ctor.
A server corresponds to an instance of a servlet container, and a service can be composed of multiple ctor INS, but these conneins must be an engine. The engine represents an actual physical or virtual machine, because Tomcat can implement clusters, the configuration snippets are as follows:
Java code
- <Service name = "Catalina">
- <Connector Port = "8080" protocol = "HTTP/1.1"
- Connectiontimeout = "20000"
- Redirectport = "8443" type = "regxph" text = "yourobjectname"/>
- <Connector Port = "8009" protocol = "AJP/1.3" redirectport = "8443"/>
- <Engine...>
- ....
- </Engine>
- </Service>
Today we will talk about it. We will continue to sort out what we have already seen in the future.