之前的文章已經介紹過如何使用HttpClusterApi
進行去中心化的HTTP集群服務訪問,這一章主要詳細講述如何使用HttpClusterApi
,主要包括如何定義節點,創建服務接口和使用接口描述不同情況下的WebApi服務。最后通過HttpClusterApi簡便地
調用百度的一些雲服務接口。
介紹
通過名稱大概也能了解它的功能,通過它可以描述和調用不同的webapi服務應用;它提供了不同Url對應不同服務綁定和創建接口代理調用功能,從而讓使用者通過接口的方式即可完成webapi的調用並不像傳統WebHttpRequest或HttpClient那樣編寫大量繁瑣的基礎代碼。
方法
組件提供了以下方法來添加服務地址
HttpClusterApi AddHost(string url, string host, int weight = 10)//設置url對應節點的host信息,默認權重是10,權重值可以根據自己實際情況來配置 HttpClusterApi AddHost(string url, params string[] host)//設置url對應節點的host信息,默認權重是10 HttpClusterApi SetNode(string url, IApiNode node)//設置url對應的節點信息
Url
參數是一個正則表達式,用於匹配請求的url;當url值為*
的時候該host是最低級匹配項,當沒有任何匹配host的情況下才使用'*'對應的host.
INodeSourceHandler NodeSourceHandler { get; set; }
在之前的文章已經有所介紹,是用於自定義集群信息源,通過這個屬性可以綁定集群信息來源,這樣使用者就可以通過數據庫,緩存或第方服務來加載集群負載信息.
public T Create<T>()
方法是創建一個接口代理,通過代理操作即可實現具體的HTTP請求,組件對接口的定義具有一定的限制性,雖然不用繼承某些基礎接口,但要通過一些組件提供的Attribute
定義在方法或參數上.
public ClusterStats Stats()
方法獲取統計信息,可以得到每個url對應不同host的調用情況統計.
線程安全問題
HttpClusterApi
是一個線程安全類,定義后可以在任意線程中同時使用;由於內部使用連接池的方式進行請求,所以並不用擔心數據訪問沖突的情況出現.Create<T>
返回的代理對象也是線程安全的,所以只需要創建一個接口實例接口即可隨意調用.
接口定義
組件通過接口的方式來進行請求處理,所以並不需要編寫任何基礎的HTTP通訊代碼,為了達到實際應用的需要,組件提供一些Attribute
來代替基礎代碼的編寫.下面介紹一些這些Attribute
的作用.
請求描述
組件暫只支持GET,POST,PUT,DELETE這幾種請求描述,這些屬性只能標記在接口方法上,用於描述方法指向那種請求方式.Route
屬性用於描述請求的路徑,默認是根路徑並使用方法名稱作為URL
[AttributeUsage(AttributeTargets.Method)] public class GetAttribute : Attribute { public string Route { get; set; } } [AttributeUsage(AttributeTargets.Method)] public class PostAttribute : Attribute { public string Route { get; set; } } [AttributeUsage(AttributeTargets.Method)] public class DelAttribute : Attribute { public string Route { get; set; } } [AttributeUsage(AttributeTargets.Method)] public class PutAttribute : Attribute { public string Route { get; set; } }
數據轉換器
數據轉換器用於描述請求和響應數據流的處理方式,組件暫只提供兩種轉換器FormUrlFormater
和JsonFormater
,分別對應的Content-Type是:application/json
和application/x-www-form-urlencoded
.如果這兩種都不能滿足實際應用需要的情況下可以通過繼承以下對象
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Class)] public abstract class FormaterAttribute : Attribute, IClientBodyFormater { public abstract string ContentType { get; } public abstract void Serialization(object data, PipeStream stream); public abstract object Deserialization(BeetleX.Buffers.PipeStream stream, Type type, int length); }
數據轉換器可以標識在接口或方法上,如果方法有標識的情況下則方法標識的轉換器優先使用.如果沒有標記轉換器組件默認使用FormUrlFormater
參數描述
在HTTP請求中主要有三種類型的參數,分別是Header
,QueryString
和Body;如果接口方法標記為POST或PUT的情況,方法參數默認是Body參數類型,會寫入到HTTP的Body中.組件提供兩個Attribute
來描述參數應用到Header
,和QueryString
CHeader
可以用於接口或方法上,並可以同時標記多個;當用在接口或方法的時候需要指定name和value.如果用在參數name和value都可以缺省,自動拿參數名和參數值.CHeader的內容會自動寫入HTTP的header里.
CQuery
可以用於接口或方法上,並可以同時標記多個;當用在接口或方法的時候需要指定name和value.如果用在參數name和value都可以缺省,自動拿參數名和參數值.CQuery的內容會自動附加到URL上,並進行URL編碼
SSL訪問
組件並不需要針對SSL做特別的配置,會自動根據添加的host是不是https
來確定,如果是https
情況下組件會自動針對這host啟用SSL配置.
百度車牌識別接口實現
考慮到實際應用的便利性,以下簡單使用組件描述一下百度雲下的車牌識別調用.
引用組件
接口功能定義
調用這個接口主要涉及到兩個方法,先是獲取access_token
,然后再調用識別方法;針對這兩個方法定義接口如下:
[BaiduApiFormater] public interface IBaiduApi { [Get(Route = "oauth/2.0/token")] [CQuery("client_id", "HiSRszPD******mqHfIz7VOrg")] [CQuery("client_secret", "y7MxdEIItD******YqtalU6b4iF")] Task<token> GetToken(string grant_type = "client_credentials"); [Post(Route = "rest/2.0/ocr/v1/license_plate")] Task<PlateData> Plate([CQuery]string access_token, string image, string multi_detect = "false"); }
由於百度的數據提交是application/x-www-form-urlencoded
返回是josn;所以需要簡單地實現一個對應的數據解釋器
public class BaiduApiFormater : BeetleX.FastHttpApi.Clients.FormUrlFormater { public override object Deserialization(PipeStream stream, Type type, int length) { using (stream.LockFree()) { if (type == null) { using (System.IO.StreamReader streamReader = new System.IO.StreamReader(stream)) using (JsonTextReader reader = new JsonTextReader(streamReader)) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(); object token = jsonSerializer.Deserialize(reader); return token; } } else { using (StreamReader streamReader = new StreamReader(stream)) { JsonSerializer serializer = new JsonSerializer(); object result = serializer.Deserialize(streamReader, type); return result; } } } } }
相關工作准備好之后就可以使用接口進行功能調用了
BeetleX.FastHttpApi.Clients.HttpClusterApi httpClusterApi = new BeetleX.FastHttpApi.Clients.HttpClusterApi(); httpClusterApi.AddHost("*", "https://aip.baidubce.com"); IBaiduApi api = httpClusterApi.Create<IBaiduApi>(); var token = await api.GetToken(); var result = await api.Plate(token.access_token, GetImageData());
這樣一個百度車牌識別的接口調用就完成了,使用上是不是比傳統的WebHttpRequest和httpclient要方便很多?