OkHttp架構解析

OkHttp架構解析

Dispatcher分發器

內部維護隊列與線程池,完成請求的調配。markdown

問題一:請求發送到哪裏去?架構

Dispatcher是保存同步和異步Call的地方,並負責執行異步AsyncCall。併發

  • 針對同步請求,Dispatcher使用了一個Deque保存了同步任務;
  • 針對異步請求,Dispatcher使用了兩個隊列Deque,一個保存準備執行的請求(readyAsyncCalls),一個保存正在執行的請求(runningAsyncCalls)
  • 爲何要用兩個呢?由於Dispatcher默認支持最大的併發請求是64個,單個Host最多執行5個併發請求,若是超過,則Call會先被放入到readyAsyncCall中,當出現空閒的線程時,再將readyAsyncCall中的線程移入到runningAsynCalls中,執行請求。

異步請求流程:框架

  1. 異步請求 Call (RealCall)—>enqueue()
  2. RealCall 的enqueue()
  3. dispatcher 的enqueue():將請求添加到等待執行的異步請求隊列中
  4. 不斷從readyAsyncCalls中取出要執行的請求放到runningAsyncCalls中,並將readyAsyncCalls中的移除,若是其中的runningAsynCalls不滿,且call佔用的host小於最大數量,則將call加入到runningAsyncCalls中執行
getResponseWithInterceptorChain();
複製代碼

問題二:如何從ready移動到running?異步

每次任務結束後,都會在ready中讀取一個任務放進running中。socket

每一個請求執行完成就會從running移除,同時進行第一步相同邏輯的判斷,決定是否移動。this

client.dispatcher().finished(this);
複製代碼

問題三:分發器的線程池是怎麼定義的?spa

無等待,最大併發。SynchronousQueue : 無容量的隊列。線程

  • 爲何使用線程池?

緣由:因爲請求數量較大,請求的生命週期較短,會致使頻繁的建立和銷燬請求,同時也會頻繁的建立和銷燬該請求對應的線程,有可能會形成內存抖動等問題,因此使用了線程池。設計

  • 爲何這麼設計線程池?

我的理解:由於在請求發送時,分發器已經維護兩個隊列,這兩個隊列框架能夠自身進行維護,若是發到線程池裏還有一個隊列的話,就表明着會有三個隊列,在線程池還要再次等待,會致使效率低下

Interceptor攔截器

完成整個請求過程

Http請求的過程:DNS解析-->創建Tcp/Ip鏈接-->使用socket對象的輸出流寫出http的報文

相關文章
相關標籤/搜索