Tomcat 源代码分析之Socket通信
Tomcat 源代码分析之Socket通讯?Tomcat?源代码分析之Socket通讯此系列文章皆为Tomcat 7.0代码代码分析。?1.
Tomcat 源代码分析之Socket通讯
?
Tomcat?源代码分析之Socket通讯
此系列文章皆为Tomcat 7.0代码代码分析。
?
1.????Socket通讯:
Tomcat对于?Socket的处理方式主要分为以下几种:
?
- ?BIO方式:采用Java阻塞Socket通讯的方式处理连接。
- ?NIO方式:之前采用BIO(阻塞方式),现在由于在Java1.4之后引入NIO,提供了NIO的实现。
- APR方式:为了和本地机器更好的集成,有更高的性能,例如一些高级的系统IO功能(sendfile, epoll and OpenSSL),本地操作的处理(shared memory, NT pipes and Unix sockets以及OS Level的功能(random number generation, system status, etc),Tomcat使用JNI调用处理Socket链接。
- AJP和ARP结合的方式。
- AJP方式:通过AJP协议进行通讯?:?AJP主要用于Apache的HTTP服务器和Servlet Web容器之间通讯,它是Packet_Oriented的,换句话说,它发送给浏览器(其他Web Server)的数据是Packet(s),得到Servlet?容器的响应也是Packet(s),这里有特殊情况,如果Servlet?容器发送的数据是二进制的,则直接发送给浏览器。此外,AJP还可以重用和Servlet容器之间的Socket连接(Socket Connection),降低创建开销。?具体请看:http://httpd.apache.org/docs/2.2/mod/mod_proxy_ajp.html。
2.????模型介绍
Connector由ProtocolHandler和一个连接端口组成,ProtocolHandler使用以上介绍的各种方式处理Socket。
根据配置选取不同的ProtocolHandler实现类的代码如下:
?
Java代码??
- /**?
- ?????*?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);??
- ????????????}??
- ????????}??
- ??
- ????}??
?
?
其相应的配置例子如下:
?
Java代码??
- <Connector?port="8080"?protocol="HTTP/1.1"??
- ???????????????connectionTimeout="20000"??
- ???????????????redirectPort="8443"?/>??
?
?
Connector调用ProtocolHandler对象处理Socket,主要代码在该Connector类的startInternal()里,如下
?
Java代码??
- /**?
- ?????*?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();??
- }??
?
而ProtocolHandler对象会启动一个相应的AbstractEndpoint对象来创建ServerSocket,监听服务相应的端口,并启动线程池处理消息。
ProtocolHandler对象启动AbstractEndpoint对象的代码在org.apache.coyote.AbstractProtocolHandler类里,如下:
?
Java代码??
- @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;??
- ????????}??
- }??
?
各种不同的ProtocolHandler对应的AbstractEndpoint如下:
ProtocolHandler
AbstractEndpoint
AjpAprProtocol
AprEndpoint
AjpProtocol
JIoEndpoint
Http11AprProtocol
AprEndpoint
Http11NioProtocol
NioEndpoint
Http11Protocol
JIoEndpoint
不同协议处理方式请看这个类的实现:AprEndpoint,JIoEndpoint,NioEndpoint。
JIoEndpoint采用BIO方式处理,NioEndpoint采用NIO的方式处理,AprEndpoint调用大量的Poll的大量native方法处理Socket。具体不再一一介绍。
我们最后为这三个组件画出一个简单的模型,如下:
3.????Tomcat中Server,Service和Connector之间的关系:
一个Server包含多个Service,而一个Service由多个Connector组成。
一个Server对应一个Servlet容器的实例,而一个Service可以由多个Connector组成,但是这些Connector必须是一个Engine的,Engine代表一台实际的物理或者虚拟机器,因为Tomcat可以实现集群的,配置片段示例如下:
?
Java代码??
- <Service?name="Catalina">??
- ????????<Connector?port="8080"?protocol="HTTP/1.1"??
- ???????????????connectionTimeout="20000"??
- ???????????????redirectPort="8443"?/>??
- ????????<Connector?port="8009"?protocol="AJP/1.3"?redirectPort="8443"?/>??
- ???????<Engine??…>??
- ???????????????….??
- ???????</Engine>??
- </Service>??
?
今天就讲到这里了,后续继续把自己已看的东西整理出来。