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

jetty http client 實現(xiàn)分析

系統(tǒng) 1998 0

背景


談到http client,可能大多數(shù)想到就是apache的那個http client 或者jdk自帶的urlconnection,也許有人會考慮使用netty

無論如何,jetty的高性能實現(xiàn)總歸是讓人感到好奇,接下來我們一探究竟


樣例


我們結(jié)合樣例代碼具體分析


  • 初始化
      httpClient = new HttpClient();
httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
httpClient.setMaxConnectionsPerAddress(10);
httpClient.setThreadPool(new QueuedThreadPool(20)); // max 20 threads
httpClient.setTimeout(5000); // 5 seconds timeout; if no server reply, the request expire
httpClient.start();
    


  • 運行
                     ContentExchange exchange = new ContentExchange(true) {
			@Override
			protected void onResponseComplete() throws IOException {
				if (getResponseStatus() == 200) {
					String content = getResponseContent();
					System.out.println(content);
				}
			}

			@Override
			protected void onExpire() {
				System.out.println("time out");
			}
		};
		exchange.setMethod("GET");
		exchange.setURL("http://127.0.0.1:8080/simple?id=x");
		httpClient.send(exchange);
    

代碼分為兩段

  • 初始化:設置httpclient
  • 運行:實例化ContentExchange,定義callback,本例定義了兩個常用的callback:onResponseComplete 和onExpire,更多的callbac可參考 官方文檔
  • APP在調(diào)用 httpClient.send(exchange);后不會象往常一樣等待返回而是立即返回, 如果有結(jié)果或者超時會通過上面的callback通知到APP



httpclient的原理及實現(xiàn)

1 ) httpclient的模型



  • SelectConnector: 作為一個connection管理器,封裝了selector和connection
  • HttpDestination:一個host的抽象一個HttpClient會連接到多個HttpDestination
  • HttpExchange:一次http請求的封裝,一個HttpDestination會有多個HttpExchange以及多個AsyncHttpConnection
  • AsyncHttpConnection:HttpClient對某個HttpDestination的一個網(wǎng)絡連接,底層包含一個對應的socket, 可復用來完成多次請求, 如果空閑太久會被廢棄
  • SelectChannelEndPoint:socket的封裝,AsyncHttpConnection和SelectChannelEndPoint一一對應, 但AsyncHttpConnection承載了更多的東西
  • HttpGenerator:生成http request,在jetty server中負責生成http response
  • HttpParser: 解析http response, 在jetty server中負責解析http request
  • ThreadPool: 線程池,httpclient需要使用線程池配合完成無阻塞IO,這個會在后面的httpclient整體架構(gòu)分析中詳述
  • Timeout:一個已時間排序的鏈表結(jié)構(gòu),鏈表中存儲需要過期執(zhí)行的task,這個會在后面流程分析詳述


2) httpclient的整體架構(gòu)



http client 分為3組線程配合完成


  • selector線程組:數(shù)目 可設置,默認為1,從_change隊列中獲取socket注冊并 掃描操作系統(tǒng)級別的網(wǎng)絡事件, 通常是socket 可讀, 可寫的信息,一旦發(fā)現(xiàn)有socket可讀寫,會將相關socket任務丟入_jobs隊列供worker線程執(zhí)行
  • worker線程組:數(shù)目 根據(jù)并發(fā)的情況決定,從 _jobs隊列獲取任務,如果任務阻塞會丟入_changes隊列異步等待通知再干活
  • tick線程:數(shù)目1個,專門用于監(jiān)控超時的請求以及空閑太久的連接
  • 所有的線程都來自線程池,所以線程池最小為3,否則無法work


3) 典型的場景分析
模擬一次請求


3.1 ) httpclient初始化


  • 1-2設置兩個超時鏈表,一個是超時請求鏈表,一個是超時連接鏈表
  • 3 啟動httpbuffer
  • 4 啟動線程池
  • 5 啟動SelectConnector,此時會啟動selector線程任務
  • 6 啟動tick線程任務


3.2)jetty http client runtime


3.2.1)httpClient.send(exchange)到底干了什么


  • 1-2正如樣例代碼所示,APP設置HttpExchange,然后httpclient的send方法
  • 2.1-2.2 httpclient根據(jù)httpexchange獲取對應http destination,并調(diào)用其send方法
  • 2.2.1 將次請求加入請求超時鏈表
  • 2.2.2 - 2.2.3 獲取空閑連接,如果沒有,則產(chǎn)生一個新的連接,并調(diào)用select進行注冊,否則直接使用該連接,并將此連接丟入 _jobs隊列讓worker線程完成請求
  • 此時客戶端就這樣無阻塞的完成了


3.2.2)select線程如何參與這個場景




  • 1-3 selector線程從_change隊列獲取到新的socket, 開始實例化SelectChannelEndPoint
  • 4 通知http desination連接完成,于是http detination將次連接丟入連接超時鏈表
  • 5-6 將此連接/請求丟入_jobs隊列供worker線程使用
  • 其實在selector線程內(nèi)部還有一個該死的任務來處理空閑太久的socket,這個其實和tick線程有些重復了,我想這主要是因為jetty http client復用jetty server中select的結(jié)果

3.2.3)worker線程又如何參與這個場景



  • worker線程從隊列中獲取任務
  • 1.1 通過此連接發(fā)送請求,請求內(nèi)容http generator產(chǎn)生
  • 1.2 一發(fā)完請求立即通過http parser讀取響應,如果服務器夠快,通常會讀到響應
  • 1.3 如果服務器不能及時響應,那么調(diào)用SelectChannelEndPoint的updateKey。向select更新此時感興趣讀, 并等待select異步通知
  • 此時worker線程并不會阻塞等待服務返回,而是返回到線程池中去完成別的請求任務

3.2.4)tick線程又干了什么



  • 輪詢兩個鏈表_timeoutQ、 _idleTimeoutQ,沒啥事休眠200ms
  • 請求超時鏈表_timeoutQ
      • 1 從鏈表中刪除自己
      • 2 執(zhí)行鏈表取出的task,一個http exchang中匿名內(nèi)部類實例
      • 2.1 執(zhí)行APP 定義的callback: onExpire函數(shù)
      • 2.2 http desination專門維護一個exchange list來跟蹤進行中的請求,此時調(diào)用其exchangeExpired, 刪除list中該請求(可能此時list并沒有該請求)
      • 2.3 關閉連接
  • 連接超時鏈表_idleTimeoutQ
      • 1從鏈表中刪除自己
      • 2 關閉連接
      • http desination 維護了兩個list:_connections和 _idle,前者跟蹤該host的所有連接, 后者跟蹤該host的所有空閑連接,此時也會從這兩個list刪除連接


小結(jié)


從jetty http client應該能感知到一個高性能的客戶端的某種設計模式


  • worker 線程異步干活,使得app線程無阻塞,app線程通常在web 應用中也是一種服務線程,所以無阻塞特別重要, 想想在jetty server中使用jetty client的場景
  • select 線程通知網(wǎng)絡ready事件,使得worker線程無阻塞,如果沒有select線程,worker線程也失去了意義, 對于app線程來說無非是壓力堆積到了worker線程這邊,worker線程遲早是瓶頸
  • tick線程,一種解決超時問題的設計


但這種模式未必適合那種性能很好且穩(wěn)定的cache server,比如redis,memcache之類,如果后端處理夠快, 少量線程甚至單線程+隊列都能work,但無論如何比起常規(guī)的連接池模式強了不少

jetty http client 實現(xiàn)分析


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

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

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

【本文對您有幫助就好】

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

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: www.一级毛片 | 久国产视频 | 四虎视频网站 | 欧美三级做爰在线 | 人人爽影院 | 欧美一级午夜免费视频你懂的 | 成年视频xxxxxx在线 | 免费a级毛片大学生免费观看 | 色综合亚洲七七久久桃花影院 | 久久国产乱子伦精品免费不卡 | 久久久99精品 | 日韩毛片在线影视 | 真人实干一级毛片aa免费 | www.一级毛片 | 哥也操| 免费99视频有精品视频高清 | 日本一级在线播放线观看免 | 国产欧美亚洲精品第二区首页 | 欧美一级免费片 | www.色婷婷 | 国产精品高清免费网站 | 91亚洲精品国产第一区 | 中文字幕在线观看免费 | 国产亚洲一区二区麻豆 | 亚洲区视频 | 在线精品免费视频 | 久久99久久 | 国产亚洲精品97在线观看 | 丁香婷婷网 | 国语一区 | 欧美www| 亚洲精品视频在线观看视频 | 手机看片日韩日韩国产在线看 | 亚洲一区二区中文字5566 | 四虎午夜影院 | 欧美超级碰碰 | 亚洲精品网址 | 在线黄色影院 | 亚洲第一在线 | 欧美一欧美一区二三区性 | 在线观看色 |