首页 > 其他 > 详细

tomcat源码分析-Connector初始化与启动

时间:2016-05-04 02:04:36      阅读:301      评论:0      收藏:0      [点我收藏+]

? ? 一个应用应用服务器的性能很大程度上取决于网络通信模块的实现,因而Connector模块对于tomcat来说是重中之重。从tomcat5开始,默认的连接器实现为Coyote实现(orag.apache.tomcat:tomcat-coyote:7.0.57),本文基于coyote实现会回答如下两个问题:

  • ? ? 一个http请求是怎么被tomcat监听到的,会有那些处理;
  • ? ? ajp协议干什么用的。

一、Connector配置

? ? 通过对Container的初始化分析,我们很自然的会回过头来看conf/server.xml的配置,其中配置了2个Connector。?

Xml代码??bubuko.com,布布扣
  1. <Connector?port="8080"?protocol="HTTP/1.1"??
  2. ???????????????connectionTimeout="20000"??
  3. ???????????????redirectPort="8443"?/>??
  4. <Connector?port="8009"?protocol="AJP/1.3"?redirectPort="8443"?/>??

为什么会有多个Connector呢?我们部署服务器的时候,通常会有2种方式:

? ? 1 直接部署tomcat,在浏览器中请求http与tomcat直连
? ? 2 部署一个nginx作反向代理,tomcat与nginx直连

这就是上面两种配置,通过协议protocol来区分。所以多个connector的好处是通过不同的协议,是tomcat服务器能够随着http的应用场景,服务器架构的升级而兼容起来。

? ? 好的,现在配置了2个Connector,那么继续思考一下,Connector是通信过程,如果是你你会怎么设计?显然需要做3件事:

(1)监听端口,创建服务端与客户端的链接;
(2)获取到客户端请求的socket数据,并对Socket数据进行解析和包装成Http请求数据格式;
(3)将包装后的数据交给Container处理

通过源码来分析,Connector有两个属性:protocolHandler(协议)和adapter(适配器),其中protocolHandler完成的是步骤(1)(2),adapter完成的是步骤(3)。

?

二、Connector初始化

? ? 1. Connector构造函数

? ? 在Connector的构造方法中,通过反射生成protocolHandler。

Java代码??bubuko.com,布布扣
  1. public?Connector(String?protocol)?{??
  2. ????setProtocol(protocol);??
  3. ????//?Instantiate?protocol?handler??
  4. ????try?{??
  5. ????????Class<?>?clazz?=?Class.forName(protocolHandlerClassName);??
  6. ????????this.protocolHandler?=?(ProtocolHandler)?clazz.newInstance();??
  7. ????}?catch?(Exception?e)?{??
  8. ????????log.error(sm.getString(??
  9. ????????????????"coyoteConnector.protocolHandlerInstantiationFailed"),?e);??
  10. ????}??
  11. }??
  12. ??
  13. public?void?setProtocol(String?protocol)?{??
  14. ??
  15. ????????if?(AprLifecycleListener.isAprAvailable())?{??
  16. ????????????if?("HTTP/1.1".equals(protocol))?{??
  17. ????????????????setProtocolHandlerClassName??
  18. ????????????????????("org.apache.coyote.http11.Http11AprProtocol");??
  19. ????????????}?else?if?("AJP/1.3".equals(protocol))?{??
  20. ????????????????setProtocolHandlerClassName??
  21. ????????????????????("org.apache.coyote.ajp.AjpAprProtocol");??
  22. ????????????}?else?if?(protocol?!=?null)?{??
  23. ????????????????setProtocolHandlerClassName(protocol);??
  24. ????????????}?else?{??
  25. ????????????????setProtocolHandlerClassName??
  26. ????????????????????("org.apache.coyote.http11.Http11AprProtocol");??
  27. ????????????}??
  28. ????????}?else?{??
  29. ????????????if?("HTTP/1.1".equals(protocol))?{??
  30. ????????????????setProtocolHandlerClassName??
  31. ????????????????????("org.apache.coyote.http11.Http11Protocol");??
  32. ????????????}?else?if?("AJP/1.3".equals(protocol))?{??
  33. ????????????????setProtocolHandlerClassName??
  34. ????????????????????("org.apache.coyote.ajp.AjpProtocol");??
  35. ????????????}?else?if?(protocol?!=?null)?{??
  36. ????????????????setProtocolHandlerClassName(protocol);??
  37. ????????????}??
  38. ????????}??
  39. ??
  40. ????}??

?协议的设置在conf/server.xml中配置,由setProtocol来赋值,tomcat提供了6种协议:

?

bubuko.com,布布扣
?

由上面6个类可知,对于http/ajp协议,tomcat均提供了三种运行模式,及BIO、NIO、APR,BIO即传统的blocking io,性能是最差的,APR是通过安装apr和native,从操作系统层面解决异步IO问题,能大幅提高性能,最省心也能较大幅度提高性能的是NIO,只需将Connector的protocol配成"org.apache.coyote.http11.Http11NioProtocol"即可。

? ? 为了便于分析,这里只分析Http11Protocol。由类图可以看到,归根结底Http11Protocol是ProtocolHandler的实现,在Http11Protocol的构造方法中,对成员变量endpoint和cHandler进行初始化

Java代码??bubuko.com,布布扣
  1. public?Http11Protocol()?{??
  2. ????????endpoint?=?new?JIoEndpoint();??
  3. ????????cHandler?=?new?Http11ConnectionHandler(this);??
  4. ????????((JIoEndpoint)?endpoint).setHandler(cHandler);??
  5. ????????setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);??
  6. ????????setSoTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);??
  7. ????????setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY);??
  8. ????}??

?,这两个很重要,在后面会讲到。

? ??继续到Connector代码中,由前面提到的tomcat启动过程知道,会调用Connector两个方法init和start。而端口的绑定和监听则分别在这两个方法中完成。

?

? ? 2. Connector的init()方法

? ? 调用的是Connector的initInternal()方法,主要做了3件事

Java代码??bubuko.com,布布扣
  1. protected?void?initInternal()?throws?LifecycleException?{??
  2. ??
  3. ????????super.initInternal();??
  4. ??
  5. ????????//?step?1.?Initialize?adapter??
  6. ????????adapter?=?new?CoyoteAdapter(this);??
  7. ????????protocolHandler.setAdapter(adapter);??
  8. ??
  9. ????????//?Make?sure?parseBodyMethodsSet?has?a?default??
  10. ????????if(?null?==?parseBodyMethodsSet?)?{??
  11. ????????????setParseBodyMethods(getParseBodyMethods());??
  12. ????????}??
  13. ??
  14. ????????if?(protocolHandler.isAprRequired()?&&??
  15. ????????????????!AprLifecycleListener.isAprAvailable())?{??
  16. ????????????//??
  17. ????????}??
  18. ??
  19. ????????try?{??
  20. ????????????//?step?2??
  21. ????????????protocolHandler.init();??
  22. ????????}?catch?(Exception?e)?{??
  23. ????????????//??
  24. ????????}??
  25. ??
  26. ????????//?step?3?Initialize?mapper?listener??
  27. ????????mapperListener.init();??
  28. ????}??

步骤2中Http11Protocol的init方法,最终会调用到其父类AbstractProtocol的init方法,在这个方法里面对endpoint(Http11Protocol使用的是JIoEndPoint)进行了初始化。

Java代码??bubuko.com,布布扣
  1. public?void?init()?throws?Exception?{??
  2. ????????//?...??
  3. ??
  4. ????????String?endpointName?=?getName();??
  5. ????????endpoint.setName(endpointName.substring(1,?endpointName.length()-1));??
  6. ??
  7. ????????try?{??
  8. ????????????endpoint.init();??
  9. ????????}?catch?(Exception?ex)?{??
  10. ????????????//??
  11. ????????}??
  12. ????}??

?endpoint.init()在AbstractEndpoint中,完成了对需要监听的端口的绑定。

Java代码??bubuko.com,布布扣
  1. public?final?void?init()?throws?Exception?{??
  2. ????????if?(bindOnInit)?{??
  3. ????????????bind();??
  4. ????????????bindState?=?BindState.BOUND_ON_INIT;??
  5. ????????}??
  6. ????}??

?在JIoEndpoint的bind()中完成了对端口的绑定。

?

三、Connector启动

? ??Connector的启动会调用start方法,在startInternal方法中,

Java代码??bubuko.com,布布扣
  1. protected?void?startInternal()?throws?LifecycleException?{??
  2. ??
  3. ????????//?Validate?settings?before?starting??
  4. ????????if?(getPort()?<?0)?{??
  5. ????????????//??
  6. ????????}??
  7. ??
  8. ????????setState(LifecycleState.STARTING);?//?发送STARTING事件??
  9. ??
  10. ????????try?{??
  11. ????????????protocolHandler.start();?//?启动端口监听??
  12. ????????}?catch?(Exception?e)?{??
  13. ????????????//??
  14. ????????}??
  15. ??
  16. ????????mapperListener.start();?//?这个很重要,后面会讲到??
  17. ????}??

?可以看到,start相对init是调用了对应的start方法。其中,protocolHandler.start();即调用了Http11Protocol的start方法。最终调用了调用了JIoEndpoint的startInternal方法,初始化了处理连接请求的线程池(默认最大线程数200个),开启Acceptor线程接收请求。

Java代码??bubuko.com,布布扣
  1. public?void?startInternal()?throws?Exception?{??
  2. ??
  3. ????????if?(!running)?{??
  4. ????????????running?=?true;??
  5. ????????????paused?=?false;??
  6. ??
  7. ????????????//?Create?worker?collection??
  8. ????????????if?(getExecutor()?==?null)?{??
  9. ????????????????createExecutor();??
  10. ????????????}??
  11. ??
  12. ????????????initializeConnectionLatch();??
  13. ??
  14. ????????????startAcceptorThreads();??
  15. ??
  16. ????????????//?Start?async?timeout?thread??
  17. ????????????Thread?timeoutThread?=?new?Thread(new?AsyncTimeout(),??
  18. ????????????????????getName()?+?"-AsyncTimeout");??
  19. ????????????timeoutThread.setPriority(threadPriority);??
  20. ????????????timeoutThread.setDaemon(true);??
  21. ????????????timeoutThread.start();??
  22. ????????}??
  23. ????}??

? ??

四、一个http请求在Connector中所经历的代码逻辑

? ? 先来个粗犷的印象,

Code代码??bubuko.com,布布扣
  1. LifecycleBase?implements?Lifecycle??
  2. start()?Lifecycle??
  3. ??startInternal()?LifecycleBase??
  4. ??
  5. ------------------------------??
  6. ??
  7. Catalina#load()??
  8. ??StandardServer#init()??
  9. ????StandService[i]#init()??
  10. ??????Container[i]#init()??
  11. ??????Executor[i]#init()??
  12. ??????Connector[i]#init()??
  13. ??
  14. Connector#initInternal()??
  15. ??adapter?=?new?CoyoteAdapter(this)??
  16. ??AbstractProtocol?extends?ProtocolHandler.setAdapter(adapter)??
  17. ??protocolHandler.init()??
  18. ??mapperListener.init()??
  19. ??
  20. AbstractProtocol?implements?ProtocolHandler#init()??
  21. ??AbstractEndpoint#init()??
  22. ????bind()??
  23. ??
  24. ------------------------------??
  25. ??
  26. Catalina#start()??
  27. ??if?(getServer()?==?null)?load();??
  28. ??StandardServer#start()??
  29. ????StandardService[i]#start()??
  30. ??????Container#start()??
  31. ??????Executor[i]#start()??
  32. ??????Connector[i]#start()??
  33. Connector#startInternal()??
  34. ??AbstractProtocol?implements?ProtocolHandler#start()??
  35. ????AbstractEndpoint#start()??
  36. ??mapperListener.start()??
  37. ??
  38. JIoEndpoint#startInternal()??
  39. ??createExecutor()??
  40. ??initializeConnectionLatch()??
  41. ??startAcceptorThreads()??
  42. ??
  43. AbstractEndpoint#startAcceptorThreads()??
  44. ??acceptors[i]?=?createAcceptor()??
  45. ??new?Thread(acceptors[i]).start()??
  46. ??
  47. JIoEndpoint.Acceptor?implements?Runnable??
  48. ??Socket?socket?=?serverSocketFactory.acceptSocket(serverSocket)??
  49. ??processSocket(socket)??
  50. ????SocketWrapper<Socket>?wrapper?=?new?SocketWrapper<Socket>(socket)??
  51. ????getExecutor().execute(new?SocketProcessor(wrapper))??
  52. ??
  53. SocketProcessor?implements?Runnable??
  54. ??state?=?handler.process(socket,status);??
  55. ??
  56. Http11Protocol?...?extends?AbstractProtocol<S>??
  57. ???Http11ConnectionHandler?extends?AbstractConnectionHandler?implements?Handler??
  58. AbstractProtocol??
  59. ???AbstractConnectionHandler?implements?AbstractEndpoint.Handler??
  60. ??????SocketState?process(SocketWrapper<S>?wrapper,?SocketStatus?status)??
  61. ????????state?=?processor.process(wrapper)??
  62. ??
  63. AbstractHttp11Processor??
  64. ??SocketState?process(SocketWrapper<S>?socketWrapper)??
  65. ????adapter.service(request,?response)??
  66. ????

?在上文中有分析Connector在启动的时候会监听端口。继续以JIoEndpoint为例,在其Accptor类中:

Java代码??bubuko.com,布布扣
  1. protected?class?Acceptor?extends?AbstractEndpoint.Acceptor?{??
  2. ????@Override??
  3. ????public?void?run()?{??
  4. ????????while?(running)?{??
  5. ????????????//??
  6. ????????????try?{??
  7. ????????????????//当前连接数??
  8. ????????????????countUpOrAwaitConnection();??
  9. ????????????????Socket?socket?=?null;??
  10. ????????????????try?{??
  11. ????????????????????//取出队列中的连接请求??
  12. ????????????????????socket?=?serverSocketFactory.acceptSocket(serverSocket);??
  13. ????????????????}?catch?(IOException?ioe)?{??
  14. ????????????????????countDownConnection();??
  15. ????????????????}??
  16. ????????????????if?(running?&&?!paused?&&?setSocketOptions(socket))?{??
  17. ????????????????????//处理请求??
  18. ????????????????????if?(!processSocket(socket))?{??
  19. ????????????????????????countDownConnection();??
  20. ????????????????????????closeSocket(socket);??
  21. ????????????????????}??
  22. ????????????????}?else?{??
  23. ????????????????????countDownConnection();??
  24. ????????????????????//?Close?socket?right?away??
  25. ????????????????????closeSocket(socket);??
  26. ????????????????}??
  27. ????????????}???
  28. ????????????//??
  29. ????????}??
  30. ????}??
  31. }??

?在上面的代码中,socket = serverSocketFactory.acceptSocket(serverSocket);与客户端建立连接,将连接的socket交给processSocket(socket)来处理。在processSocket中,对socket进行包装一下交给线程池来处理:

Java代码??bubuko.com,布布扣
  1. protected?boolean?processSocket(Socket?socket)?{??
  2. ????try?{??
  3. ????????SocketWrapper<Socket>?wrapper?=?new?SocketWrapper<Socket>(socket);??
  4. ????????wrapper.setKeepAliveLeft(getMaxKeepAliveRequests());??
  5. ????????wrapper.setSecure(isSSLEnabled());??
  6. ????????//交给线程池处理连接??
  7. ????????getExecutor().execute(new?SocketProcessor(wrapper));??
  8. ????}???
  9. ????//??
  10. ????return?true;??
  11. }??

?线程池处理的任务SocketProccessor,通过代码分析:

Java代码??bubuko.com,布布扣
  1. protected?class?SocketProcessor?implements?Runnable?{??
  2. ??
  3. ????protected?SocketWrapper<Socket>?socket?=?null;??
  4. ????protected?SocketStatus?status?=?null;??
  5. ??
  6. ????@Override??
  7. ????public?void?run()?{??
  8. ????????boolean?launch?=?false;??
  9. ????????synchronized?(socket)?{??
  10. ????????????SocketState?state?=?SocketState.OPEN;??
  11. ????????????try?{??
  12. ????????????????serverSocketFactory.handshake(socket.getSocket());??
  13. ????????????}???
  14. ????????????//??
  15. ????????????if?((state?!=?SocketState.CLOSED))?{??
  16. ????????????????//委派给Handler来处理??
  17. ????????????????if?(status?==?null)?{??
  18. ????????????????????state?=?handler.process(socket,?SocketStatus.OPEN_READ);??
  19. ????????????????}?else?{??
  20. ????????????????????state?=?handler.process(socket,status);??
  21. ????????????????}??
  22. ????????????}}}??
  23. ????????????//??
  24. }??

?即在SocketProcessor中,将Socket交给handler处理,这个handler就是在Http11Protocol的构造方法中赋值的Http11ConnectionHandler,在该类的父类process方法中通过请求的状态,来创建Http11Processor处理器进行相应的处理,切到Http11Proccessor的父类AbstractHttp11Proccessor中。

Java代码??bubuko.com,布布扣
  1. public?SocketState?process(SocketWrapper?socketWrapper)?{??
  2. ????RequestInfo?rp?=?request.getRequestProcessor();??
  3. ????rp.setStage(org.apache.coyote.Constants.STAGE_PARSE);??
  4. ??
  5. ????//?Setting?up?the?I/O??
  6. ????setSocketWrapper(socketWrapper);??
  7. ????getInputBuffer().init(socketWrapper,?endpoint);??
  8. ????getOutputBuffer().init(socketWrapper,?endpoint);??
  9. ??
  10. ????while?(!getErrorState().isError()?&&?keepAlive?&&?!comet?&&?!isAsync()?&&??
  11. ????????????upgradeInbound?==?null?&&??
  12. ????????????httpUpgradeHandler?==?null?&&?!endpoint.isPaused())?{??
  13. ????????//??
  14. ????????if?(!getErrorState().isError())?{??
  15. ????????????//?Setting?up?filters,?and?parse?some?request?headers??
  16. ????????????rp.setStage(org.apache.coyote.Constants.STAGE_PREPARE);??
  17. ????????????try?{??
  18. ????????????????//请求预处理??
  19. ????????????????prepareRequest();??
  20. ????????????}???
  21. ????????????//??
  22. ????????}??
  23. ????????//??
  24. ????????if?(!getErrorState().isError())?{??
  25. ????????????try?{??
  26. ????????????????rp.setStage(org.apache.coyote.Constants.STAGE_SERVICE);??
  27. ????????????????//交由适配器处理??
  28. ????????????????adapter.service(request,?response);??
  29. ??
  30. ????????????????if(keepAlive?&&?!getErrorState().isError()?&&?(??
  31. ????????????????????????response.getErrorException()?!=?null?||??
  32. ????????????????????????????????(!isAsync()?&&??
  33. ????????????????????????????????statusDropsConnection(response.getStatus()))))?{??
  34. ????????????????????setErrorState(ErrorState.CLOSE_CLEAN,?null);??
  35. ????????????????}??
  36. ????????????????setCometTimeouts(socketWrapper);??
  37. ????????????}???
  38. ????????}??
  39. ????}??
  40. ????//??
  41. }????????????

代码很长,删掉的部分比较多,在这个方法里,可以看到Request和Response的生成,从Socket中获取请求数据,keep-alive处理,数据包装等,最后交给了CoyoteAdapter的service方法。

tomcat源码分析-Connector初始化与启动

原文:http://wely.iteye.com/blog/2295171

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!