亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

tomcat連接器

系統(tǒng) 1958 0

????? Connector是Tomcat最核心的組件之一,負責處理一個WebServer最核心的連接管理、Net IO、線程(可選)、協(xié)議解析和處理的工作。
一、連接器介紹
在開始Connector探索之路之前,先看看Connector幾個關鍵字

  • NIO:Tomcat可以利用Java比較新的NIO技術,提升高并發(fā)下的Socket性能
  • AJP:Apache JServ Protocol,AJP的提出當然還是為了解決java亙古不變的問題——性能,AJP協(xié)議是基于包的長連接協(xié)議,以減少前端Proxy與Tomcat連接Socket連接創(chuàng)建的代價,目前Apache通過JK和AJP_ROXY的方式支持AJP協(xié)議,需要注意的是,雖然Nginx作為代理服務器性能強勁,但其只能通過HTTP PROXY的方式與后端的Tomcat聯(lián)系,因此如果從作為代理服務器的角度上講,在這種情況下Nginx未必會比Apache體現(xiàn)出更優(yōu)的性能
  • APR/Native:Apache Portable Runtime,還是一個詞,性能。APR的提出利用Native代碼更好地解決性能問題,更好地與本地服務器(linux)打交道。讓我們看看Tomcat文檔對APR的介紹
Tomcat6文檔 寫道
Tomcat can use the Apache Portable Runtime to provide superior scalability, performance, and better integration with native server technologies. The Apache Portable Runtime is a highly portable library that is at the heart of Apache HTTP Server 2.x. APR has many uses, including access to advanced IO functionality (such as sendfile, epoll and OpenSSL), OS level functionality (random number generation, system status, etc), and native process handling (shared memory, NT pipes and Unix sockets).
These features allows making Tomcat a general purpose webserver, will enable much better integration with other native web technologies, and overall make Java much more viable as a full fledged webserver platform rather than simply a backend focused technology.

通過對如上名詞的組合,Tomcat組成了如下的Connector系列:

  • Http11Protocol:支持HTTP1.1協(xié)議的連接器
  • Http11NioProtocol:支持HTTP1.1 協(xié)議+ NIO的連接器
  • Http11AprProtocol:使用APR技術處理連接的連接器
  • AjpProtocol:支持AJP協(xié)議的連接器
  • AjpAprProtocol:使用APR技術處理連接的連接器

二、范例
????? 我們以最簡單的Http11Protocol為例,看看從請求進來到處理完畢,連接器部件是處理處理的。首先我們利用Tomcat組件組成我們一個最簡單的WebServer,其具備如下功能:

  • 監(jiān)停某個端口,接受客戶端的請求,并將請求分配給處理線程
  • 處理線程處理請求,分析HTTP1.1請求,封裝Request/Response對象,并將請求由請求處理器處理
  • 實現(xiàn)最簡單的請求處理器,向客戶端打印Hello World

代碼非常簡單,首先是主功能(這里,我們利用JDK5.0的線程池,連接器不再管理線程功能):

Java代碼?? 收藏代碼
  1. package?ray.tomcat.test;??
  2. ??
  3. import?java.util.concurrent.BlockingQueue;??
  4. import?java.util.concurrent.LinkedBlockingQueue;??
  5. import?java.util.concurrent.ThreadPoolExecutor;??
  6. import?java.util.concurrent.TimeUnit;??
  7. ??
  8. import?org.apache.coyote.http11.Http11Protocol;??
  9. ??
  10. public? class?TomcatMainV2??
  11. {??
  12. ???? public? static? void?main(String[]?args)? throws?Exception??
  13. ????{??
  14. ????????Http11Protocol?protocol?=? new?Http11Protocol();??
  15. ????????protocol.setPort( 8000);??
  16. ????????ThreadPoolExecutor?threadPoolExecutor?=?createThreadPoolExecutor();??
  17. ????????threadPoolExecutor.prestartCoreThread();??
  18. ????????protocol.setExecutor(threadPoolExecutor);??
  19. ????????protocol.setAdapter( new?MyHandler());??
  20. ????????protocol.init();??
  21. ????????protocol.start();??
  22. ????}??
  23. ??
  24. ???? public? static?ThreadPoolExecutor?createThreadPoolExecutor()??
  25. ????{??
  26. ???????? int?corePoolSize?=? 2;??
  27. ???????? int?maximumPoolSize?=? 10;??
  28. ???????? long?keepAliveTime?=? 60;??
  29. ????????TimeUnit?unit?=?TimeUnit.SECONDS;??
  30. ????????BlockingQueue<Runnable>?workQueue?=? new?LinkedBlockingQueue<Runnable>();??
  31. ????????ThreadPoolExecutor?threadPoolExecutor?=? new?ThreadPoolExecutor(??
  32. ????????????????corePoolSize,?maximumPoolSize,?keepAliveTime,?unit,?workQueue);??
  33. ???????? return?threadPoolExecutor;??
  34. ????}??
  35. }??
?

請求處理器向客戶端打引Hello World,代碼如下

Java代碼?? 收藏代碼
  1. package?ray.tomcat.test;??
  2. ??
  3. import?java.io.ByteArrayOutputStream;??
  4. import?java.io.OutputStreamWriter;??
  5. import?java.io.PrintWriter;??
  6. ??
  7. import?org.apache.coyote.Adapter;??
  8. import?org.apache.coyote.Request;??
  9. import?org.apache.coyote.Response;??
  10. import?org.apache.tomcat.util.buf.ByteChunk;??
  11. import?org.apache.tomcat.util.net.SocketStatus;??
  12. ??
  13. public? class?MyHandler? implements?Adapter??
  14. {??
  15. ???? //支持Comet,Servlet3.0將對Comet提供支持,Tomcat6目前是非標準的實現(xiàn)??
  16. ???? public? boolean?event(Request?req,?Response?res,?SocketStatus?status)??
  17. ???????????? throws?Exception??
  18. ????{??
  19. ????????System.out.println( "event");??
  20. ???????? return? false;??
  21. ????}??
  22. ??
  23. ???? //請求處理??
  24. ???? public? void?service(Request?req,?Response?res)? throws?Exception??
  25. ????{??
  26. ????????System.out.println( "service");??
  27. ??
  28. ????????ByteArrayOutputStream?baos?=? new?ByteArrayOutputStream();??
  29. ????????PrintWriter?writer?=? new?PrintWriter( new?OutputStreamWriter(baos));??
  30. ????????writer.println( "Hello?World");??
  31. ????????writer.flush();??
  32. ??
  33. ????????ByteChunk?byteChunk?=? new?ByteChunk();??
  34. ????????byteChunk.append(baos.toByteArray(),? 0,?baos.size());??
  35. ????????res.doWrite(byteChunk);??
  36. ????}?????
  37. }??
?

???? 運行主程序,在瀏覽器中輸入http://127.0.0.1:8000,我們可以看到打印”Hello World”
三、分析
???? 以如上Http11Protocol為例,我們可以看到,Tomcat實現(xiàn)一個最簡單的處理Web請求的代碼其實非常簡單,其主要包括如下核心處理類:

  • Http11Protocol:Http1.1協(xié)議處理入口類,其本身沒有太多邏輯,對請求主要由JIoEndPoint類處理
  • Http11Protocol$Http11ConnectionHandler:連接管理器,管理連接處理隊列,并分配Http11Processor對請求進行處理
  • Http11Processor:請求處理器,負責HTTP1.0協(xié)議相關的工作,包括解析請求和處理響應信息,并調用Adapter做實際的處理工作,如上我們看到了我們自定義的Adapter實現(xiàn)響應”Hello World”
  • JIoEndPoint:監(jiān)停端口,啟動接受線程準備接收請求,在請求接受后轉給工作線程處理
  • JIoEndPoint$Acceptor:請求接收器,接收后將Socket分配給工作線程繼續(xù)后續(xù)處理
  • JIoEndPoint$Worker:工作線程,使用Handler來處理請求,對于我們的HTTP1.1協(xié)議來說,其實現(xiàn)是Http11Protocol$Http11ConnectionHandler。這部分不是必須的,也可以選擇JDK的concurrent包的線程池

????? 實際上各種連接器實現(xiàn)基本大同小異,基本上都是由如上部分組合而成

????? 1.初始化:首先,還是從入口開始,先看看初始化init

Java代碼?? 收藏代碼
  1. public? void?init()? throws?Exception?{??
  2. ????????endpoint.setName(getName());??
  3. ????????endpoint.setHandler(cHandler);? //請求處理器,對于HTTP1.1協(xié)議,是Http11Protocol$Http11ConnectionHandler??
  4. ??
  5. ?????????
  6. //?初始化ServerSocket工廠類,如果需SSL/TLS支持,使用JSSESocketFactory/PureTLSSocketFactory??
  7. .?.?.?(略)?????????
  8. ?????????????? //主要的初始化過程實際是在endpoint(JIoEndpoint)??
  9. ????????endpoint.init();??
  10. ????????.?.?.?(略)??
  11. ????}??

????? Http11Protocol的初始化非常簡單,準備好ServerSocket工廠,調用JIoEndPoint的初始化。讓我們接下來看看JIoEndPoint的初始化過程

Java代碼?? 收藏代碼
  1. public? void?init()??
  2. ???????? throws?Exception?{??
  3. ??
  4. ???????? if?(initialized)??
  5. ???????????? return;??
  6. ?????????
  7. ???????? //?Initialize?thread?count?defaults?for?acceptor??
  8. ???????? //?請求接收處理線程,這個值實際1已經(jīng)足夠??
  9. ???????? if?(acceptorThreadCount?==? 0)?{??
  10. ????????????acceptorThreadCount?=? 1;??
  11. ????????}??
  12. ???????? if?(serverSocketFactory?==? null)?{??
  13. ????????????serverSocketFactory?=?ServerSocketFactory.getDefault();??
  14. ????????}??
  15. ?????????
  16. ???????? //創(chuàng)建監(jiān)停ServerSocket,port為監(jiān)聽端口,address為監(jiān)停地址??
  17. ???????? //?backlog為連接請求隊列容量(@param?backlog?how?many?connections?are?queued)??
  18. ???????? if?(serverSocket?==? null)?{??
  19. ???????????? try?{??
  20. ???????????????? if?(address?==? null)?{??
  21. ????????????????????serverSocket?=?serverSocketFactory.createSocket(port,?backlog);??
  22. ????????????????}? else?{??
  23. ????????????????????serverSocket?=?serverSocketFactory.createSocket(port,?backlog,?address);??
  24. ????????????????}??
  25. ????????????}? catch?(BindException?be)?{??
  26. ???????????????? throw? new?BindException(be.getMessage()?+? ":"?+?port);??
  27. ????????????}??
  28. ????????}??
  29. ???????? //if(?serverTimeout?>=?0?)??
  30. ???????? //????serverSocket.setSoTimeout(?serverTimeout?);??
  31. ?????????
  32. ????????initialized?=? true;????
  33. ????}??

??????? 可以看到,監(jiān)停端口在此處準備就緒

Java代碼?? 收藏代碼
  1. public? void?start()??
  2. ????? throws?Exception?{??
  3. ????? //?Initialize?socket?if?not?done?before??
  4. ????? if?(!initialized)?{??
  5. ?????????init();??
  6. ?????}??
  7. ????? if?(!running)?{??
  8. ?????????running?=? true;??
  9. ?????????paused?=? false;??
  10. ??
  11. ????????? //?Create?worker?collection??
  12. ????????? //?初始化工作線程池,有WorkerStack(Tomcat自實現(xiàn))和Executor(JDK?concurrent包)兩種實現(xiàn)??
  13. ????????? if?(executor?==? null)?{??
  14. ?????????????workers?=? new?WorkerStack(maxThreads);??
  15. ?????????}??
  16. ??
  17. ????????? //?Start?acceptor?threads??
  18. ????????? //?啟動請求連接接收處理線程??
  19. ????????? for?( int?i?=? 0;?i?<?acceptorThreadCount;?i++)?{??
  20. ?????????????Thread?acceptorThread?=? new?Thread( new?Acceptor(),?getName()?+? "-Acceptor-"?+?i);??
  21. ?????????????acceptorThread.setPriority(threadPriority);??
  22. ?????????????acceptorThread.setDaemon(daemon);? //設置是否daemon參數(shù),默認為true??
  23. ?????????????acceptorThread.start();??
  24. ?????????}??
  25. ?????}??
  26. ?}??
?


????? 2.準備好連接處理:初始化完畢,準備好連接處理,準備接收連接上來,同樣的,Http11Protocol的start基本沒干啥事,調用一下JIoEndPoint的start,我們來看看JIoEndPoint的start

Java代碼?? 收藏代碼
  1. public? void?start()??
  2. ????? throws?Exception?{??
  3. ????? //?Initialize?socket?if?not?done?before??
  4. ????? if?(!initialized)?{??
  5. ?????????init();??
  6. ?????}??
  7. ????? if?(!running)?{??
  8. ?????????running?=? true;??
  9. ?????????paused?=? false;??
  10. ??
  11. ????????? //?Create?worker?collection??
  12. ????????? //?初始化工作線程池,有WorkerStack(Tomcat自實現(xiàn))和Executor(JDK?concurrent包)兩種實現(xiàn)??
  13. ????????? if?(executor?==? null)?{??
  14. ?????????????workers?=? new?WorkerStack(maxThreads);??
  15. ?????????}??
  16. ??
  17. ????????? //?Start?acceptor?threads??
  18. ????????? //?啟動請求連接接收處理線程??
  19. ????????? for?( int?i?=? 0;?i?<?acceptorThreadCount;?i++)?{??
  20. ?????????????Thread?acceptorThread?=? new?Thread( new?Acceptor(),?getName()?+? "-Acceptor-"?+?i);??
  21. ?????????????acceptorThread.setPriority(threadPriority);??
  22. ?????????????acceptorThread.setDaemon(daemon);? //設置是否daemon參數(shù),默認為true??
  23. ?????????????acceptorThread.start();??
  24. ?????????}??
  25. ?????}??
  26. ?}??

????? 主要處理的事情無非就是準備和工作線程(處理具體請求的線程度池,可選,也可以使用JDK5.0的線程池),連接請求接收處理線程(代碼中,一般acceptorThreadCount=1)

????? 3.連接請求接收處理:準備就緒,可以連接入請求了?,F(xiàn)在工作已經(jīng)轉到了Acceptor(JIoEndPoint$Acceptor)這里,我們看看Acceptor到底做了些啥

Java代碼?? 收藏代碼
  1. public? void?run()?{??
  2. ??
  3. ???????????? //?Loop?until?we?receive?a?shutdown?command??
  4. ???????????? while?(running)?{??
  5. ????????????????.?.?.?(略)??
  6. ???????????????????? //阻塞等待客戶端連接??
  7. ????????????????????Socket?socket?=?serverSocketFactory.acceptSocket(serverSocket);??
  8. ????????????????????serverSocketFactory.initSocket(socket);??
  9. ???????????????????? //?Hand?this?socket?off?to?an?appropriate?processor??
  10. ???????????????????? if?(!processSocket(socket))?{??
  11. ???????????????????????? //?Close?socket?right?away??
  12. ???????????????????????? try?{??
  13. ????????????????????????????socket.close();??
  14. ????????????????????????}? catch?(IOException?e)?{??
  15. ???????????????????????????? //?Ignore??
  16. ????????????????????????}??
  17. ????????????????????}??
  18. ??????????????????.?.?.?(略)??
  19. ????????????}??
  20. ?}??
  21. .?.?.?(略)??
  22. ???? protected? boolean?processSocket(Socket?socket)?{??
  23. ???????? try?{??
  24. ???????????? //由工作線程繼續(xù)后續(xù)的處理??
  25. ???????????? if?(executor?==? null)?{??
  26. ????????????????getWorkerThread().assign(socket);??
  27. ????????????}? else?{??
  28. ????????????????executor.execute( new?SocketProcessor(socket));??
  29. ????????????}??
  30. ????????}? catch?(Throwable?t)?{??
  31. ????????????.?.?.?(略)?????????????
  32. return? false;??
  33. ????????}??
  34. ???????? return? true;??
  35. ????}??

?????? 實際上也沒有什么復雜的工作,無非就是有連接上來之后,將連接轉交給工作線程(SocketProcessor)去處理

?????? 4.工作線程:SocketProcessor

Java代碼?? 收藏代碼
  1. public? void?run()?{??
  2. ???????????? //?Process?the?request?from?this?socket??
  3. ???????????? if?(!setSocketOptions(socket)?||?!handler.process(socket))?{??
  4. ???????????????? //?Close?socket??
  5. ???????????????? try?{??
  6. ????????????????????socket.close();??
  7. ????????????????}? catch?(IOException?e)?{??
  8. ????????????????}??
  9. ????????????}??
  10. ???????????? //?Finish?up?this?request??
  11. ????????????socket?=? null;??
  12. ????????}?????

??? 工作線程主要是設置一下Socket參數(shù),然后將請求轉交給handler去處理,需要注意一下如下幾個連接參數(shù)的意義:

  • SO_LINGER:若設置了SO_LINGER并確定了非零的超時間隔,則closesocket()調用阻塞進程,直到所剩數(shù)據(jù)發(fā)送完畢或超時。這種關閉稱為“優(yōu)雅的”關 閉。請注意如果套接口置為非阻塞且SO_LINGER設為非零超時,則closesocket()調用將以WSAEWOULDBLOCK錯誤返回。若在一個流類套接口上設置了SO_DONTLINGER,則closesocket()調用立即返回。但是,如果可能,排隊的數(shù)據(jù)將在套接口關閉前發(fā)送。請注意,在這種情況下WINDOWS套接口實現(xiàn)將在 一段不確定的時間內保留套接口以及其他資源(TIME_WAIT),這對于想用所以套接口的應用程序來說有一定影響。默認此參數(shù)不打開
  • TCP_NODELAY:是否打開Nagle,默認打開,使用Nagle算法是為了避免多次發(fā)送小的分組,而是累計到一定程度或者超過一定時間后才一起發(fā)送。對于AJP連接,可能需要關注一下這個選項。
  • SO_TIMEOUT:JDK API注釋如下,With this option set to a non-zero timeout,a read() call on the InputStream associated with this Socket will block for only this amount of time.? If the timeout expires, a java.net.SocketTimeoutException is raised, though the Socket is still valid. The option must be enabled prior to entering the blocking operation to have effect. The timeout must be > 0。默認設置的是60秒

??????? 關于默認的設置,可以參見org.apache.coyote.http11.Constants定義
????? 5.最終請求終于回到了Handler,此處的Handler實現(xiàn)是org.apache.coyote.http11.Http11Processor,其主要處理一些HTTP協(xié)議性細節(jié)的東西,此處代碼不再列出,有興趣可以自行讀代碼。最終請求終于回到了我們的Adapter對象,一個請求處理完畢,功德圓滿。

tomcat連接器


更多文章、技術交流、商務合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 一区不卡在线观看 | 97爱爱爱 | 国产香港特级一级毛片 | 99久久精品免费精品国产 | 久久最近最新中文字幕大全 | 国产亚洲综合色就色 | 天天躁日日2018躁狠狠躁 | 91日韩精品天海翼在线观看 | 亚洲精品久久久久综合91 | 九九艹| 色花堂国产精品第二页 | 黄色男人的天堂 | 久久96国产精品久久久 | 天天干天天操 | 成在线人永久免费播放视频 | 大狠狠大臿蕉香蕉大视频 | www天天干| 久久天天丁香婷婷中文字幕 | 日韩va | 尹人香蕉久久99天天 | 狠狠色狠狠色综合久久第一次 | 日韩永久免费视频 | 一级毛片成人免费看免费不卡 | 一本影院| 国产亚洲片 | 四虎在线免费播放 | 国产ar高清视频+视频 | 日韩亚洲欧美一区二区三区 | 国内精品久久久久影院网站 | 色婷婷久久综合中文久久一本 | 欧美日韩在线成人免费视频大全 | 国产精品在线播放 | 九九热在线精品视频 | 大伊香蕉精品视频在线天堂 | 天天天天天天操 | 亚洲涩涩精品专区 | 国产欧美日本亚洲精品五区 | 狠狠操综合 | 国产永久一区二区三区 | jizz国产精品免费麻豆 | 一区精品在线 |