深刻剖析OkHttp系列(一) 來自官方的OkHttp設計思想(中英互譯)

本文譯自OkHttp官方Wiki文檔git

The HTTP client’s job is to accept your request and produce its response. This is simple in theory but it gets tricky in practice.github

Callsweb

該HttpClient的做用是接收你的請求並生成響應。 這在理論上來講是很簡單的, 可是在實踐上, 卻很棘手。算法

Requests緩存

Each HTTP request contains a URL, a method (like GET or POST), and a list of headers. Requests may also contain a body: a data stream of a specific content type.服務器

每一個Http請求都包含一個URL, 一個方法(如GET或POST), 還有一系列的header。 Request中可能會包含一個Body: 一個特定類型的數據流。cookie

Responses網絡

The response answers the request with a code (like 200 for success or 404 for not found), headers, and its own optional body.app

Response會以一個返回碼(像請求成功的200 或 找不到請求的404), 一系列的請求頭,以及它自身的body來響應你的請求。 less

Rewriting Requests

When you provide OkHttp with an HTTP request, you’re describing the request at a high-level: 「fetch me this URL with these headers.」 For correctness and efficiency, OkHttp rewrites your request before transmitting it.

當你經過OkHttp發起一個Http請求時, 其實你是在一個high-level上描述一個請求: 「經過這些請求頭訪問這個URL」。 爲了確保準確性和高效性, Okhttp會再請求傳輸以前, 重寫你的請求。

OkHttp may add headers that are absent from the original request, including Content-Length, Transfer-Encoding, User-Agent, Host, Connection, and Content-Type. It will add an Accept-Encoding header for transparent response compression unless the header is already present. If you’ve got cookies, OkHttp will add a Cookie header with them.

OkHttp可能會再原始請求中添加缺乏的請求頭, 包含Content-Length, Transfer-Encoding, User-Agent, Host, Connection, 和 Content-Type。 OkHttp將會爲透明壓縮響應添加一個Accept-Encoding請求頭, 除非該請求頭已經有了。若是你要獲取cookies, OkHttp會添加一個Cookie請求頭。

Some requests will have a cached response. When this cached response isn’t fresh, OkHttp can do a conditional GET to download an updated response if it’s newer than what’s cached. This requires headers like If-Modified-Since and If-None-Match to be added.

有些請求將會緩存響應。當這個緩存響應不是最新時, OkHttp會額外的執行一次Get請求去下載更新的響應, 若是這個響應比緩存的更新的話。這就須要像 If-Modified-Since and If-None-Match這樣的請求頭的添加。

Rewriting Responses

If transparent compression was used, OkHttp will drop the corresponding response headers Content-Encoding and Content-Length because they don’t apply to the decompressed response body.

若是要使用透明壓縮, OkHttp將會刪除相應的響應頭Content-Encoding 和 Content-Length, 由於這些請求頭是不適用於壓縮響應體的。

If a conditional GET was successful, responses from the network and cache are merged as directed by the spec.

若是一個Get請求成功了, 網絡和緩存的響應會直接按規範合併。

Follow-up Requests

When your requested URL has moved, the webserver will return a response code like 302 to indicate the document’s new URL. OkHttp will follow the redirect to retrieve a final response.

當你的請求URL被移動了, 服務器將會返回一個code, 如302,來指向文檔的新URL。 OkHttp會遵循重定向來修正最終的響應。

If the response issues an authorization challenge, OkHttp will ask the Authenticator (if one is configured) to satisfy the challenge. If the authenticator supplies a credential, the request is retried with that credential included.

若是響應發出受權申請,OkHttp將會詢問驗證器(若是配置了的話)來響應申請。若是驗證器提供了一個憑證, 此次請求會帶着憑證從新請求。

Retrying Requests

Sometimes connections fail: either a pooled connection was stale and disconnected, or the webserver itself couldn’t be reached. OkHttp will retry the request with a different route if one is available.

有時鏈接失敗: 池鏈接失效並斷開鏈接, 或 服務器自己沒法被訪問。 OkHttp會經過不一樣的有效路由重試請求。

Calls

With rewrites, redirects, follow-ups and retries, your simple request may yield many requests and responses. OkHttp uses Call to model the task of satisfying your request through however many intermediate requests and responses are necessary. Typically this isn’t many! But it’s comforting to know that your code will continue to work if your URLs are redirected or if you failover to an alternate IP address.

經過重寫,重定向,後續追蹤和重試, 你的簡單的請求可能會產生不少請求和響應。OkHttp使用Call來模擬知足你請求的任務, 然而不少中間的請求和響應是必需的。一般這種狀況不是不少!可是, 若是你的URL被重定向, 或者故障被轉移到備用的IP地址,你的代碼將依然有效的執行,這一點很棒!

Calls are executed in one of two ways:

Synchronous: your thread blocks until the response is readable. Asynchronous: you enqueue the request on any thread, and get called back on another thread when the response is readable.

Calls can be canceled from any thread. This will fail the call if it hasn’t yet completed! Code that is writing the request body or reading the response body will suffer an IOException when its call is canceled.

Calls能夠被如下兩種方式之一執行:
同步: 你的線程會阻塞, 知道響應返回。
異步: 你能夠將請求加入任何線程, 並在響應返回時, 在其餘線程回調

Calls能夠任意線程被取消。 這將會在請求尚未完成時,使其失敗。 在Call被取消後,正在寫請求體或讀響應體的代碼將會拋出IO異常。

Dispatch

For synchronous calls, you bring your own thread and are responsible for managing how many simultaneous requests you make. Too many simultaneous connections wastes resources; too few harms latency.

For asynchronous calls, Dispatcher implements policy for maximum simultaneous requests. You can set maximums per-webserver (default is 5), and overall (default is 64).

對於同步請求, 你能夠本身建立線程並負責管理同時發出的請求數。 同時發出太多請求會浪費資源, 太少會存在延遲的弊端。 對於異步請求, Dispatcher實現了最大同時請求的策略。 你能夠設置每一個服務器的最大鏈接數(默認是5), 和總鏈接數(默認是64)。


Connections

Although you provide only the URL, OkHttp plans its connection to your webserver using three types: URL, Address, and Route.

儘管你只提供URL, OkHttp使用三種形式鏈接服務器:URL, 地址 和 路由。

URLS

URLs (like github.com/square/okht…) are fundamental to HTTP and the Internet. In addition to being a universal, decentralized naming scheme for everything on the web, they also specify how to access web resources.

URL是Http和網絡的基礎。除了用來在Web上做爲一個統一的, 分散的命名方案外,它們還指明瞭如何來訪問網絡資源。

URLs are abstract:

They specify that the call may be plaintext (http) or encrypted (https), but not which cryptographic algorithms should be used. Nor do they specify how to verify the peer's certificates (the HostnameVerifier) or which certificates can be trusted (the SSLSocketFactory). They don't specify whether a specific proxy server should be used or how to authenticate with that proxy server.

URL是抽象的:
它們指明瞭call能夠是明文或密文, 可是沒有指明應該使用哪些加密算法。
它們沒指明怎麼去驗證對方的證書, 或哪些證書能夠被信任。
它們沒有指明一個指定的代理服務是否能夠被使用,或如何使用代理服務進行身份驗證。

They're also concrete: each URL identifies a specific path (like /square/okhttp) and query (like ?q=sharks&lang=en). Each webserver hosts many URLs.

URL也是具體的:
每一個URL指定了一個特定的路徑(如like/square/okhttp)和查詢(如?q=sharks&lang=en)。每一個服務器持有不少URLS。

Addresses

Addresses specify a webserver (like github.com) and all of the static configuration necessary to connect to that server: the port number, HTTPS settings, and preferred network protocols (like HTTP/2 or SPDY).

Addresses指定了一個Web服務器和鏈接到這個服務器所需的全部靜態配置: 端口號, HTTPS設置和相關的網絡協議(如HTTP/2 或 SPDY)。

URLs that share the same address may also share the same underlying TCP socket connection. Sharing a connection has substantial performance benefits: lower latency, higher throughput (due to TCP slow start) and conserved battery. OkHttp uses a ConnectionPool that automatically reuses HTTP/1.x connections and multiplexes HTTP/2 and SPDY connections.

共享相同地址的URLs可能也會共享相同的底層TCP套接字鏈接。 共享鏈接具備顯著的性能優點:
更低的延遲
更高的吞吐量(因爲TCP的慢啓動)
節省電源
OkHttp使用鏈接池, 自動重用 HTTP/1.x鏈接 並多路複用HTTP/2和SPDY鏈接。

In OkHttp some fields of the address come from the URL (scheme, hostname, port) and the rest come from the OkHttpClient.

在OkHttp中, Address的某些字段來自於URL(方案, 主機名, 端口) , 其他字段來自OkHttpClient。

Routes

Routes supply the dynamic information necessary to actually connect to a webserver. This is the specific IP address to attempt (as discovered by a DNS query), the exact proxy server to use (if a ProxySelector is in use), and which version of TLS to negotiate (for HTTPS connections).

路由提供了實際鏈接到Web服務器所需的動態信息。這是要嘗試的特定IP地址(由DNS查詢發現), 要使用的確切的代理服務器(若是使用了ProxySelector), 以及要協定的TLS版本(對於HTTPS鏈接而言)。

There may be many routes for a single address. For example, a webserver that is hosted in multiple datacenters may yield multiple IP addresses in its DNS response.

單個地址可能會有不少路由。 好比, 一個託管在多個數據中心的Web服務器, 可能會在DNS響應中產生多個IP地址。

Connections

When you request a URL with OkHttp, here's what it does:

It uses the URL and configured OkHttpClient to create an address. This address specifies how we'll connect to the webserver. It attempts to retrieve a connection with that address from the connection pool. If it doesn't find a connection in the pool, it selects a route to attempt. This usually means making a DNS request to get the server's IP addresses. It then selects a TLS version and proxy server if necessary. If it's a new route, it connects by building either a direct socket connection, a TLS tunnel (for HTTPS over an HTTP proxy), or a direct TLS connection. It does TLS handshakes as necessary. It sends the HTTP request and reads the response. If there's a problem with the connection, OkHttp will select another route and try again. This allows OkHttp to recover when a subset of a server's addresses are unreachable. It's also useful when a pooled connection is stale or if the attempted TLS version is unsupported.

當你使用OkHttp訪問一個URL時, 它作了什麼:
它使用URL和配置的OkHttpClient建立一個地址。 該地址指明瞭咱們如何鏈接Web服務器。它嘗試經過這個地址從鏈接池中恢復這個鏈接。若是再鏈接池中沒有找到鏈接,它會選擇一個路由去嘗試。這一般意味着發出一個DNS請求來獲取服務端的IP地址。 而後若是須要, 它會選擇一個TLS版本和代理服務。若是它是一個新的路由, 它會經過直接構建一個新的socket鏈接, 一個TLS通道(對於HTTP代理的HTTPS), 或者一個直接的TLS鏈接, 並根據須要進行TLS握手。

它發送一個HTTP請求並讀取響應。

若是鏈接有問題, OkHttp會選擇其餘路由並從新嘗試。這使得OkHttp當在一個服務器的地址的子集沒法訪問時,進行恢復。當池化鏈接失效, 或嘗試的TLS版本不支持時, 也是有用的。

Once the response has been received, the connection will be returned to the pool so it can be reused for a future request. Connections are evicted from the pool after a period of inactivity.

一旦響應到達, 鏈接會返回到鏈接池中, 這樣在之後的請求中就能夠複用了。 一段時間不活躍後, 鏈接會從鏈接池中被移除。
相關文章
相關標籤/搜索