注:以下內容均來源於網絡。
https://blog.csdn.net/chen213wb/article/details/81747573
https://blog.csdn.net/qq_23034515/article/details/89226635
https://www.cjavapy.com/article/50/
。。。
HTTP常用請求參數
Method |
請求方式:Get、Post、Put、Delete |
Timeout |
獲取或設置請求的超時值。(毫秒) |
ReadWriteTimeout |
獲取或設置讀取或寫入流時的超時 |
KeepAlive |
獲取或設置一個值,該值指示是否與 Internet 資源建立持久性連接。 |
ClientCertificates |
獲取或設置與此請求關聯的安全證書集合 |
Proxy |
獲取或設置請求的代理信息。 |
AllowAutoRedirect |
獲取或設置一個值,該值指示請求是否應跟隨重定向響應。 |
CookieContainer |
獲取或設置與此請求關聯的cookie。 |
Credentials |
獲取或設置請求的身份驗證信息。 |
MaximumAutomaticRedirections |
獲取或設置請求將跟隨的重定向的最大數目。 |
SendChunked |
獲取或設置一個值,該值指示是否將數據分段發送到 Internet 資源。 |
Header.ContentType |
設置請求的數據類型:application/x-www-form-urlencoded、multipart/form-data、application/json、text/xml... |
Header.ContentLength |
設置請求的數據長度 |
Header.Accept |
設置響應的數據類型:application/x-www-form-urlencoded、multipart/form-data、application/json、text/xml... |
Header.UserAgent |
客戶端的訪問類型,包括瀏覽器版本和操作系統信息 |
Header.Referer |
請求的來源地址 |
請求方式:
1、GET請求會向數據庫發索取數據的請求,從而來獲取信息,該請求就像數據庫的select操作一樣,只是用來查詢一下數據,不會修改、增加數據,不會影響資源的內容,即該請求不會產生副作用。無論進行多少次操作,結果都是一樣的。
2、與GET不同的是,PUT請求是向服務器端發送數據的,從而改變信息,該請求就像數據庫的update操作一樣,用來修改數據的內容,但是不會增加數據的種類等,也就是說無論進行多少次PUT操作,其結果並沒有不同。
3、POST請求同PUT請求類似,都是向服務器端發送數據的,但是該請求會改變數據的種類等資源,就像數據庫的insert操作一樣,會創建新的內容。幾乎目前所有的提交操作都是用POST請求的。
4、DELETE請求顧名思義,就是用來刪除某一個資源的,該請求就像數據庫的delete操作。
就像前面所講的一樣,既然PUT和POST操作都是向服務器端發送數據的,那么兩者有什么區別呢?POST主要作用在一個集合資源之上的(url),而PUT主要作用在一個具體資源之上的(url/xxx),通俗一下講就是,如URL可以在客戶端確定,那么可使用PUT,否則用POST。
綜上所述,我們可理解為以下:
1、GET /url/xxx 查看
2、PUT /url/xxx 更新
3、POST /url 創建
4、DELETE /url/xxx 刪除
數據類型:
1、application/x-www-form-urlencoded
瀏覽器的原生 form 表單,如果不設置 enctype 屬性,那么最終就會以 application/x-www-form-urlencoded 方式提交數據。提交的數據按照 key1=val1&key2=val2 的方式進行編碼,key 和 val 都進行了 URL 轉碼。大部分服務端語言都對這種方式有很好的支持。
2、multipart/form-data
我們使用表單上傳文件時,必須讓 form 的 enctyped 等於這個值。
種方式一般用來上傳文件時必須使用該種方式,各大服務端語言對它也有着良好的支持。
3、application/json
這個 Content-Type 作為響應頭大家肯定不陌生。實際上,現在越來越多的人把它作為請求頭,用來告訴服務端消息主體是序列化后的 JSON 字符串。由於 JSON 規范的流行,除了低版本 IE 之外的各大瀏覽器都原生支持 JSON.stringify,服務端語言也都有處理 JSON 的函數,使用 JSON 不會遇上什么麻煩。JSON 格式支持比鍵值對復雜得多的結構化數據,這一點也很有用。
4、text/xmlXML-RPC
協議簡單、功能夠用,各種語言的實現都有。它的使用也很廣泛,如 WordPress 的 XML-RPC Api,搜索引擎的 ping 服務等等。JavaScript 中,也有現成的庫支持以這種方式進行數據交互,能很好的支持已有的 XML-RPC 服務。 因XML 結構還是過於臃腫,一般場景用 JSON 會更靈活方便。
.NET發送HTTP請求的方式
1、HttpWebRequest
這是.NET創建者最初開發用於使用HTTP請求的標准類。使用HttpWebRequest可以讓開發者控制請求/響應流程的各個方面,如 timeouts, cookies, headers, protocols。另一個好處是HttpWebRequest類不會阻塞UI線程。例如,當您從響應很慢的API服務器下載大文件時,您的應用程序的UI不會停止響應。HttpWebRequest通常和WebResponse一起使用,一個發送請求,一個獲取數據。HttpWebRquest更為底層一些,能夠對整個訪問過程有個直觀的認識,但同時也更加復雜一些。
這種方法是早期開發者使用的方法,在當前業務中已經很少使用,由於其更加底層,需要處理一些細節,最多用於框架內部操作。
/// <summary> /// 1.通過WebRequest發送請求 /// </summary> public class SendByWebRequest { public static string Post(string url,string content) { HttpWebRequest request = null; try { request = (HttpWebRequest)WebRequest.Create(url); var data = Encoding.UTF8.GetBytes(content); request.Accept = "application/json"; // 設置響應數據的ContentType request.Method = "POST"; request.ContentType = "application/json"; // 設置請求數據的ContentType request.ContentLength = data.Length; // 設置入參 using (var stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); } // 發送請求 var response = (HttpWebResponse)request.GetResponse(); // 讀取出參 using (var resStream = response.GetResponseStream()) { using (var reader = new StreamReader(resStream, Encoding.UTF8)) { return reader.ReadToEnd(); } } } catch (Exception ex) { return null; } finally { // 釋放連接 if (request != null) request.Abort(); } } public static string Get(string url, string content) { HttpWebRequest request = null; try { request = (HttpWebRequest)WebRequest.Create(url + content); request.Accept = "application/json"; // 設置響應數據的ContentType var response = (HttpWebResponse)request.GetResponse(); // 讀取出參 using (var resStream = response.GetResponseStream()) { using (var reader = new StreamReader(resStream, Encoding.UTF8)) { return reader.ReadToEnd(); } } } catch (Exception ex) { return null; } finally { // 釋放連接 if (request != null) request.Abort(); } } }
2、WebClient
WebClient是一種更高級別的抽象,是HttpWebRequest為了簡化最常見任務而創建的,使用過程中你會發現他缺少基本的header,timeoust的設置,不過這些可以通過繼承httpwebrequest來實現。相對來說,WebClient比WebRequest更加簡單,它相當於封裝了request和response方法,不過需要說明的是,Webclient和WebRequest繼承的是不同類,兩者在繼承上沒有任何關系。
使用WebClient可能比HttpWebRequest直接使用更慢(大約幾毫秒),但卻更為簡單,減少了很多細節,代碼量也比較少。
WebClient主要面向了WEB網頁場景,在模擬Web操作時使用較為方便,但用在RestFul場景下卻比較麻煩,這時候就需要HttpClient出馬了。
/// <summary> /// 2.通過WebClient發送請求 /// </summary> public class SendByWebClient { public static string Post(string url, string content) { try { byte[] para = Encoding.UTF8.GetBytes(content); using (var client = new WebClient()) { client.Encoding = Encoding.UTF8; client.Headers.Add("Accept", "application/json"); // 設置響應數據的ContentType client.Headers.Add("Content-Type", "application/json"); // 設置請求數據的ContentType client.Headers.Add("ContentLength", para.Length.ToString()); var response = client.UploadData(url, "POST", para); return Encoding.UTF8.GetString(response); } } catch (Exception ex) { return null; } } public static string Get(string url, string content) { try { using (var client = new WebClient()) { client.Encoding = Encoding.UTF8; client.Headers.Add("Accept", "application/json"); // 設置響應數據的ContentType return client.DownloadString(url + content); } } catch (Exception ex) { return null; } } }
3、HttpClient
目前業務上使用的比較多的是HttpClient,它適合用於多次請求操作,一般設置好默認頭部后,可以進行重復多次的請求,基本上用一個實例可以提交任何的HTTP請求。此外,HttpClient提供了異步支持,可以輕松配合async await 實現異步請求。
HttpClient推薦使用單一實例共享使用,發關請求的方法推薦使用異步的方式。
/// <summary> /// 3.通過HttpClient發送請求 /// </summary> public class SendByHttpClient { public static string Post(string url, string content) { try { using (HttpClient client = new HttpClient()) { client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); // 設置響應數據的ContentType var para = new StringContent(content); para.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); // 設置請求數據的ContentType return client.PostAsync(url, para).Result.Content.ReadAsStringAsync().Result; } } catch (Exception ex) { return null; } } public static string Get(string url, string content) { try { using (HttpClient client = new HttpClient()) { client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json")); // 設置響應數據的ContentType return client.GetStringAsync(url + content).Result; } } catch (Exception ex) { return null; } } }
4、第三方類庫
如Flurl.Http,RestSharp等。
/// <summary> /// 4.通過第三方類庫發送請求 /// </summary> public class SendByFlurl { public static string Post(string url, string content) { try { //string abc = $"{url}".PostJsonAsync(content).ReceiveString().Result; return $"{url}".PostAsync(new StringContent(content, Encoding.UTF8, "application/json")).ReceiveString().Result; } catch (Exception ex) { return null; } } public static string Get(string url, string content) { try { return $"{url}{content}".GetStringAsync().Result; } catch (Exception ex) { return null; } } }
|
HttpWebRequset |
WebClient |
HttpClient |
命名空間 |
System.Net |
System.Net |
System.Net.Http |
繼承類 |
WebRequest |
Component |
HttpMessageInvoker |
支持url轉向 |
是 |
否 |
是 |
支持cookie和session |
是 |
否 |
否 |
支持用戶代理服務器 |
是 |
否 |
是 |
使用復雜度 |
高 |
低 |
低 |
擴展
REST & RPC
微服務之間的接口調用通常包含兩個部分,序列化和通信協議。常見的序列化協議包括json、xml、hession、protobuf、thrift、text、bytes等;通信比較流行的是http、soap、websockect,RPC通常基於TCP實現,常用框架例如dubbo,netty、mina、thrift。
REST:嚴格意義上說接口很規范,操作對象即為資源,對資源的四種操作(post、get、put、delete),並且參數都放在URL上,但是不嚴格的說Http+json、Http+xml,常見的http api都可以稱為Rest接口。
RPC:即我們常說的遠程過程調用,就是像調用本地方法一樣調用遠程方法,通信協議大多采用二進制方式。
HTTP vs 高性能二進制協議
HTTP相對更規范,更標准,更通用,無論哪種語言都支持HTTP協議。如果你是對外開放API,例如開放平台,外部的編程語言多種多樣,你無法拒絕對每種語言的支持,相應的,如果采用HTTP,無疑在你實現SDK之前,支持了所有語言,所以,現在開源中間件,基本最先支持的幾個協議都包含RESTful。
RPC協議性能要高的多,例如Protobuf、Thrift、Kyro等,(如果算上序列化)吞吐量大概能達到http的二倍。響應時間也更為出色。千萬不要小看這點性能損耗,公認的,微服務做的比較好的,例如,netflix、阿里,曾經都傳出過為了提升性能而合並服務。如果是交付型的項目,性能更為重要,因為你賣給客戶往往靠的就是性能上微弱的優勢。
所以,最佳實踐一般是對外REST,對內RPC,但是追求極致的性能會消耗很多額外的成本,所以一般情況下對內一般也REST,但對於個別性能要求較高的接口使用RPC。