最近項目需要使用 Java 重度調用 HTTP API 接口,於是想着封裝一個團隊公用的 HTTP client lib. 這個庫需要支持以下特性:
-
連接池管理,包括連接創建和超時、空閑連接數控制、每個 host 的連接數配置等。基本上,我們想要一個 go HTTP 標准庫自帶的連接池管理功能。
-
域名解析控制。因為調用量會比較大,因此希望在域名解析這一層做一個調用端可控的負載均衡,同時可以對每個服務器 IP 進行失敗率統計和健康度檢查。
-
Form/JSON 調用支持良好。
-
支持同步和異步調用。
在 Java 生態中,雖然有數不清的 HTTP client lib 組件庫,但是大體可以分為這三類:
-
JDK 自帶的 HttpURLConnection 標准庫;
-
Apache HttpComponents HttpClient, 以及基於該庫的 wrapper, 如 Unirest.
-
非基於 Apache HttpComponents HttpClient, 大量重寫應用層代碼的 HTTP client 組件庫,典型代表是 OkHttp.
HttpURLConnection
使用 HttpURLConnection 發起 HTTP 請求最大的優點是不需要引入額外的依賴,但是使用起來非常繁瑣,也缺乏連接池管理、域名機械控制等特性支持。以發起一個 HTTP POST 請求為例:
可以看到,使用 HttpURLConnection 發起 HTTP 請求是比較原始(low level)的,基本上你可以理解為它就是對網絡棧傳輸層(HTTP 一般為 TCP,HTTP over QUIC 是 UDP)進行了一次淺層次的封裝,操作原語就是在打開的連接上面寫請求 request 與讀響應 response.
而且 HttpURLConnection 無法支持 HTTP/2. 顯然,官方是知道這些問題的,因此在 Java 9 中,官方在標准庫中引入了一個 high level、支持 HTTP/2 的 HttpClient. 這個庫的接口封裝就非常主流到位了,發起一個簡單的 POST 請求:
封裝的最大特點是鏈式調用非常順滑,支持連接管理等特性。但是這個庫只能在 Java 9 及以后的版本使用,Java 9 和 Java 10 並不是 LTS 維護版本,而接下來的 Java 11 LTS 要在2018.09.25發布,應用到線上還需要等待一段時間。因此,雖然挺喜歡這個自帶標准庫(畢竟可以不引入三方依賴),但當前是無法在生產環境使用的。
Apache HttpComponents HttpClient
Apache HttpComponents HttpClient 的前身是 Apache Commons HttpClient, 但是 Apache Commons HttpClient 已經停止開發,如果你還在使用它,請切換到 Apache HttpComponents HttpClient 上來。
Apache HttpComponents HttpClient 支持的特性非常豐富,完全覆蓋我們的需求,使用起來也非常順手:
對 Client 細致的配置和自定義支持也是非常到位的:
完整示例請參考 ClientConfiguration.
https://hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientConfiguration.java
基本上,在 Java 原生標准庫不給力的情況下,Apache HttpComponents HttpClient 是最佳的 HTTP Client library 選擇。但這個庫當前還不支持 HTTP/2,支持 HTTP/2 的版本還處於 beta 階段(2018.09.23),因此並不適合用於 Android APP 中使用。
OkHttp
由於當前 Apache HttpComponents HttpClient 版本並不支持 HTTP/2, 而 HTTP/2 對於移動客戶端而言,無論是從握手延遲、響應延遲,還是資源開銷看都有相當吸引力。因此這就給了高層次封裝且支持 HTTP/2 的 http client lib 足夠的生存空間。其中最典型的要數OkHttp.
OkHttp 接口設計友好,支持 HTTP/2,並且在弱網和無網環境下有自動檢測和恢復機制,因此,是當前 Android APP 開發中使用最廣泛的 HTTP clilent lib 之一。
另一方面,OkHttp 提供的接口與 Java 9 中 HttpClint 接口比較類似 (嚴格講,應該是 Java 9 借鑒了 OkHttp 等開源庫的接口設計?),因此,對於喜歡減少依賴,鍾情於原生標准庫的開發者來說,在 Java 11 中,從 OkHttp 切換到標准庫是相對容易的。因此,以 OkHttp 為代表的 http 庫以后的使用場景可能會被蠶食一部分。
小結
HttpURLConnection 封裝層次太低,並且支持特性太少,不建議在項目中使用。除非你的確不想引入第三方 HTTP 依賴(如減少包大小、目標環境不提供三方庫支持等)。
Java 9 中引入的 HttpClient,封裝層次和支持特性都不錯。但是因為 Java 版本的原因,應用場景還十分有限,建議觀望一段時間再考慮在線上使用。
如果你不需要 HTTP/2特性,Apache HttpComponents HttpClient 是你的最佳選擇,比如在服務器之間的 HTTP 調用。否則,請使用 OkHttp, 如 Android 開發。
擴展閱讀
作者:行思錄
來源:https://liudanking.com/sitelog/java-http-client-lib-comparison/