欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

jetty http client 實現分析

系統 2078 0

背景


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

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


樣例


我們結合樣例代碼具體分析


  • 初始化
      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在調用 httpClient.send(exchange);后不會象往常一樣等待返回而是立即返回, 如果有結果或者超時會通過上面的callback通知到APP



httpclient的原理及實現

1 ) httpclient的模型



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


2) httpclient的整體架構



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


  • selector線程組:數目 可設置,默認為1,從_change隊列中獲取socket注冊并 掃描操作系統級別的網絡事件, 通常是socket 可讀, 可寫的信息,一旦發現有socket可讀寫,會將相關socket任務丟入_jobs隊列供worker線程執行
  • worker線程組:數目 根據并發的情況決定,從 _jobs隊列獲取任務,如果任務阻塞會丟入_changes隊列異步等待通知再干活
  • tick線程:數目1個,專門用于監控超時的請求以及空閑太久的連接
  • 所有的線程都來自線程池,所以線程池最小為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根據httpexchange獲取對應http destination,并調用其send方法
  • 2.2.1 將次請求加入請求超時鏈表
  • 2.2.2 - 2.2.3 獲取空閑連接,如果沒有,則產生一個新的連接,并調用select進行注冊,否則直接使用該連接,并將此連接丟入 _jobs隊列讓worker線程完成請求
  • 此時客戶端就這樣無阻塞的完成了


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




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

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



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

3.2.4)tick線程又干了什么



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


小結


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


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


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

jetty http client 實現分析


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

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

【本文對您有幫助就好】

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

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 一区二区免费 | 欧美精品一区二区三区免费播放 | 57pao成人永久免费视频 | 久久精品久久精品久久 | 亚洲视频 欧美视频 | 亚洲免费在线观看视频 | 精品成人一区二区 | 伊人久久艹| 亚洲午夜精品A片久久WWW软件 | 一个色综合亚洲色综合 | 日韩精品免费在线视频 | 亚洲精品电影在线观看 | 欧美a大片 | 青草娱乐极品免费视频 | 国产成人精品福利网站在线观看 | 九九99国产精品视频 | 久久一级| 亚洲欧洲日产国码在线观看 | 欧美日韩在线观看中文字幕 | 日本在线你懂的 | 九九操视频| 成人免费影院 | 一区二区三区四区在线 | 成人亚洲一区二区色情无码潘金莲 | 欧美一级毛片在线 | 日日摸夜夜添夜夜 | 日日干天天摸 | 欧美很黄视频在线观看 | 国产免费久久久久 | 九九国产 | 色综合免费| 国产精品久久久99 | 国产精品成人在线 | 色婷婷久久免费网站 | 国产精品乱码人人做人人爱 | 国产片自拍 | 国产激情在线观看 | 欧美久久天天综合香蕉伊 | 久久一区二区三区四区 | 久久草视频这里只精品 | 中国免费一级毛片 |