.NET下幾個服務框架介紹

黄舟
發布: 2017-02-06 14:22:52
原創
1945 人瀏覽過

簡介


在公司的服務多了以後,為了調用上的方便,同時為了以後的服務治理,一般都會使用一些服務框架,這裡主要介紹我知道的幾個服務框架,簡析一下這些服務框架的基本概念。


可投入生產環境使用的


以下兩個服務框架,我已經見過有公司投入到生產環境,所以對於穩定性,應該不需要有太大的擔憂。

 

ServiceStack https://github.com/ServiceStack/ServiceStack 


ServiceStack可能沒有用過,但是它的另外兩個組件,但是它的另外兩個組件,大家應該都用過,ServiceStackRedis( Redis 存取工具), ServiceStack.Text(Json序列化工具),ServiceStack就是一服務框架,可以很方便的用他來創建服務,服務是基於http的,另外提供了客戶端調用, 數據的序列化方式包含Json , xml , 二進制,Protobuf ,並且創建出來的服務帶有一定的描述。


1個http請求,有兩個東西很關鍵,請求路徑和參數,對於ServiceStack,參數即對象,即它要傳遞的參數都封裝到一個類裡面, 另外在類上打標籤,標籤內容就是請求路徑,這樣客戶端在呼叫的時候,反射出請求路徑和參數,即可發起呼叫。

 

因為ServiceStack本身已經提供了demo, 所以這裡就不寫demo了, 大家可以學習一下。

 

Hessian https://sourceforge.net/projects/hessiancsharp/ 


Hessian是一個序列化工具,同時也是一個服務框架,提供有多語言的實現,包括.net,這個組件. Net領域似乎不太有名,可能很久沒更新了。

使用Hessian的時候,首先需要定義接口,然後一式兩份,服務端來實現這些接口, 客戶端引用這些接口,然後客戶端使用了RealProxxy類做代理, 所有接口調用最終會調用代理類裡面的Invoke方法, 在Invoke方法裡面取得要呼叫的方法的名稱,參數等內容,經過序列化發送到服務端一個統一的url上, 這個url會以hessian結尾, 所以需要在web.config中配置一個handle來攔截請求, 攔截到請求後,反序列化參數, 然後透過反射發起呼叫。


這裡呼叫可以參考這篇部落格 http://www.cnblogs.com/lxsfg/archive/2008/08/27/1277777.html

ri

其他的服務框架上還有很多, JSON-RPC 但是因為沒有用過,所以這裡不做評論。


博客園內的一些服務框架

以下三個框架是我在瀏覽博客園的時候發現的,並且都是開源的,對於學習服務框架是個不錯的項目,另外我不經常上博客園,下面3個框架也是機緣巧合下看到的,博客園應該還有其他優秀的服務框架只是我沒有發現而已,如果你有發現,不妨寫到評論區,大家一起學習。

 Rabbit.Rpc http://www.cnblogs.com/ants/p/5605754.html

和Hessin的有些像,也是先定義服務接口,然後一式兩份,服務端透過繼承介面來實現具體的邏輯,對於客戶端,他是透過反射,提取出接口內的所有方法,以及方法參數及返回值信息,然後通過動態生成代碼的方式,生成一份代理類,再動態編譯,放入到容器中。 關於生成的那個代理類,所有方法都是一個統一的實現,即呼叫一個Invoke方法把方法和參數發給底層,底層組裝發送到服務端。這裡生成程式碼的方式比較好玩,可以學習一下。


另外,這個框架同時整合了服務治理,服務註冊到Zookeeper, 客戶端透過Zoopeeper拿到具體的服務位址進行呼叫。 其實到這裡,這已經不只是一個服務框架,同時包含了服務治理功能。 


我也只是粗讀了程式碼, 細節還沒理解透,想要詳細了解的可以看源碼。

 

Dyd.BaseService.ServiceCenter  http://git.oschina.net/chejiangyi/Dyd.BaseService.ServiceCenter 

看基本的功能介紹作者對這個項目都有介紹是這個項目的介紹是這個項目屬於研究性的,對於服務呼叫的客戶端,也是透過程式碼產生的方式, 具體可以參考程式碼。

另外再多介紹一下這位博友,他在博客園也有博

客 http://www.cnblogs.com/chejiangyi/  ,其下開源了數個項目 http://git.oschina.net /chejiangyi 都是一些很不錯的項目,例如調度服務,配置服務,監控服務,對於上點規模的互聯網公司,這些服務都是需要的,更可貴的是這些服務都是基於.Net的, 所以對於一些使用.Net開發的網路公司來說,有不錯的借鏡意義。

Redola.Rpc http://www.cnblogs.com/gaochundong/p/redola_yet_another_csharp_rpc_framework.html

這個是我最近發現的,該框架使用了Actor模型,序列化使用了protobuf-net,傳輸方式是基於tcp , tcp框架使用的他自己的Cowboy.WebSockets ,看介紹也實現了服務中心,但是因為我對Actor模型並不理解,所以這裡就不畫蛇添足了, 有興趣的同學可以看作者的博客。


我自己寫的服務框架

看了這麼多的服務框架,自己手癢也寫了一個,僅僅是一個服務調用的且是實驗性質的,可以作為一個參考。

框架的原理和Hession類似,先要定義接口,然後服務端實現接口, 這裡我取了個巧,我直接讓Web API中的Controller繼承了接口,所以就不需要專門定義一個Handle來攔截請求,同時也不影響Web Api的訪問,所以你即使使用了這個框架,也不妨礙你直接用http的方式進行訪問。客戶端的呼叫方式和Hession類似,也是需要定義代理,然後收集參數,

首先定義接口

.NET下幾個服務框架介紹

有了接口,接下來就是實現,這裡我使用的是Web API, 我們定義一個Controller, 這個Controller除了繼承APIController, 還繼承了接口,在這個Controller裡,實作介面具體的邏輯。 

.NET下幾個服務框架介紹

同時把這個介面所在的dll複製到客戶端,這裡要介紹一個功能,就是RealProxy, 這是.Net自帶的代理類,同時也是Hession採用的機制。 

using System;
using System.Linq;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Remoting.Proxies;
using Newtonsoft.Json;
using RestSharp;
namespace SimleRPC
{
    public class SimpleProxy : RealProxy
    {
        private readonly Uri _uri;
        public SimpleProxy(Type type, Uri uri) : base(type)
        {
            this._uri = uri;
        }
        public override IMessage Invoke(IMessage msg)
        {
            //msg参数包含调用方法的信息,这里通过封装,使信息更丰富一些
            IMethodCallMessage methodMessage = new MethodCallMessageWrapper((IMethodCallMessage)msg);
            MethodInfo methodInfo = (MethodInfo)methodMessage.MethodBase;
            ParameterInfo[] paramsInfo = methodInfo.GetParameters();  //获取方法调用参数
            //拼装path  类名即controller名, 方法名即action名  这样就表示出具体的url
            string path = "/api/" + methodInfo.DeclaringType.Name + "/" + methodInfo.Name;
            //请求类型,post or get
            bool isHttpGet = methodInfo.CustomAttributes.Any(customAttributeData => customAttributeData.AttributeType.Name == "HttpGetAttribute");
            var client = new RestClient(_uri);
            var request = new RestRequest(path, isHttpGet ? Method.GET : Method.POST);
            //构建参数
            //web api对于传参的一切规则  参考 http://www.cnblogs.com/babycool/p/3922738.html    http://www.cnblogs.com/landeanfen/p/5337072.html 两篇博客
            if (isHttpGet)
            {
                //这里默认get请求的参数都是基本类型
                for (int i = 0; i < paramsInfo.Length; i++)
                {
                    request.AddParameter(paramsInfo[i].Name, methodMessage.Args[i]);
                }
            }
            else
            {
                //对于post请求,要么没有参数(当然基本没有这种情况),要么只有一个参数(这些是受web api的限制)
                if (paramsInfo.Length > 0)
                {
                    request.AddJsonBody(methodMessage.Args[0]);
                }
            }
            // 发送请求 拿到结果
            IRestResponse response = client.Execute(request);
            var content = response.Content;
            Type returnType = methodInfo.ReturnType;     //获取调用方法返回类型,根据类型反序列化结果
            object returnValue;
            if (IsBaseType(returnType))
            {
                returnValue = Convert.ChangeType(content, returnType);
            }
            else
            {
                returnValue = JsonConvert.DeserializeObject(content, returnType); //如果是一个对象,则用json进行反序列化
            }
            return new ReturnMessage(returnValue, methodMessage.Args, methodMessage.ArgCount, methodMessage.LogicalCallContext, methodMessage);
        }
        /// <summary>
        /// 判断是否是基础类型(int long  double), string 是引用类型,但是也归到基础类型里面
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private static bool IsBaseType(Type type)
        {
            if (type == typeof(string) || type.IsPrimitive)
                return true;
            return false;
        }
    }
}
登入後複製

所有的方法呼叫都會呼叫Invoke方法,在Invoke方法內,可以拿到呼叫方法的具體訊息,例如參數,傳回值型別等。 然後透過反射和拼裝,組成一個Http請求,這裡我預設介面類別名稱即Controller的名字, 介面方法名稱即Action的名字。

最後再透過RestSharp把請求送出去。 最後根據http結果反序列化為方法傳回值所需的值。 

.NET下幾個服務框架介紹

其實對於服務端來首,Web API是否繼承了介面都不重要,如果不繼承,則介面的簽章要和Web API中方法的簽章保持一致。 

透過我寫的Demo,方法是可以調的通的, 如果有人對這個感興趣,可以再多測試一些情況。  


最後


現在很多的網路公司都有自己的RPC框架,有些是採用開源的,有些因為歷史問題,自己寫的,對於通訊方式,有基於Http的,也有基於TCP的, 還有兩種協定都相容的。 序列化方式也是多種多樣, 我上面只列舉了5個,其實在github上搜索,還有很多優秀的RPC。


RPC僅是專案發展過程中一個階段。 有了RPC以後,可以在此基礎上做很多的事情,例如:


服務治理 所有的服務在啟動的時候註冊到服務中心,客戶端在啟動的時候,從註冊中心獲取真實的地址,直接調用,不經過Nginx等代理,這裡可以在獲取真實地址上做一些權限限制,比如哪些客戶端能用,哪些客戶端不能用,能用多少個,這裡可以參考dubbo。


Http請求路徑 現在微服務很流行, 前端一個請求,可能要經過後端好幾個服務,可以在http頭上加上RequestId和RequestIndex, 把這些服務串起來,例如A->B- >C,A服務呼叫B服務的時候,如果發現http head裡面沒有RequestId, 則可以透過GuId產生一個,同時RequestIndex加1 ,B服務呼叫C服務端時候, 因為RequestId已經有了,就直接傳遞下去,同時RequestIndex加1 ,把這些資訊記錄到日誌中,透過分析,整個呼叫就串起來了,透過完整的資料就可以繪製出整個服務的呼叫連結圖。 


除了鏈路圖,因為我們可以攔截到每個服務的調用,所以我們可以記錄服務調用耗時,再加上鏈路圖,整個的服務資訊會更加完善。 

以上就是.NET下幾個服務架構介紹的內容,更多相關內容請關注PHP中文網(www.php.cn)!


相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新問題
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板