1. 程式人生 > >BeetleX之HttpClusterApi應用詳解

BeetleX之HttpClusterApi應用詳解

之前的文章已經介紹過如何使用HttpClusterApi進行去中心化的HTTP叢集服務訪問,這一章主要詳細講述如何使用HttpClusterApi,主要包括如果定義節點,建立服務介面和如果使用介面描述不同情況下的WebApi服務。最後簡單地通過HttpClusterApi來呼叫百度的一些雲服務介面。

介紹

通過名稱大概也能瞭解它的功能,通過它可以描述和呼叫不同的webapi服務應用;它提供了不同Url對應不同服務繫結和建立介面代理呼叫功能,從而讓使用者通過介面的方式即可完成webapi的呼叫並不像傳統WebHttpRequest或HttpClient那樣編寫大量繁瑣的基礎程式碼。

方法

元件提供了以下方法來新增服務地址

//設定url對應節點的host資訊,預設權重是10,權重值可以根據自己實際情況來配置
HttpClusterApi AddHost(string url, string host, int weight = 10)
//設定url對應節點的host資訊,預設權重是10
HttpClusterApi AddHost(string url, params string[] host)
//設定url對應的節點資訊
HttpClusterApi SetNode(string url, IApiNode node)

 

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; }
    }

資料轉換器

資料轉換器用於描述請求和響應資料流的處理方式,元件暫只提供兩種轉換器FormUrlFormaterJsonFormater,分別對應的Content-Type是:application/jsonapplication/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要方便很多?