說說面向服務的體系架構SOA

序言

在.Net的世界中,一說起SOA,你們想到的應該是Web Service,WCF,還有人或許也會在.NET MVC中的Web API上作上標記,而後泛泛其談!nginx

的確,微軟的這些技術也確實推進着面向服務的世界發展,固然除了微軟還有不少面向服務的開源技術,甚至在某些方面比微軟作的更加優秀。那麼什麼是面向服務,面向服務的存在是爲了解決什麼問題呢?web

說說SOA面向服務

SOA是由Garnter在1996年提出的一個概念,旨在讓軟件變的有彈性,可以迅速響應業務的需求,實現實時企業。基本理念是讓全部信息系統中須要整合的業務使用服務和接口聯繫起來,接口中立,與開發平臺和編程語言無關。這也使得異構信息系統變的可開發,「信息孤島」,重複造輪子等問題在SOA的體系架構下不攻自破。算法

簡單通俗的說就是,SOA是不一樣業務創建不一樣的服務,服務之間的能夠數據交互粗粒度的服務接口分級,這樣鬆散耦合提升服務的重用性,也讓業務邏輯變的可組合,而且每一個服務能夠根據使用狀況作出合理的分佈式部署,從而讓服務變的規範,高性能,高可用。sql

那麼接下來咱們首先來看下微軟在這方面作啦哪些貢獻,以及軟件開發是怎樣的一個變化歷程。apache

代碼複用技術的發展
編程

面向過程(應用內/過程級複用)---->面向對象(應用內/類級複用)--->面向組件(應用內/組件級複用)--->分佈式組件(應用間/組件級複用)---->面向服務(應用間/服務級複用)json

微軟面向服務提供的技術api

那麼針對上面的一張圖,作一個簡短的說明,首先是Tcp與Http協議的比較,這兩個協議各有所長:緩存

基於TCP協議:可以減小網絡傳輸字節數,下降網路開銷,效率高,可是實現複雜,且因爲協議和標準不一樣,難以進行跨平臺,和企業間的便捷通訊,而且當服務愈來愈多的時候,負載聚恆策略,服務地址管理和配置都會變得複雜和繁瑣,目前也沒有很好的開源支持。tomcat

基於Http協議:那麼他相對於Tcp來講,首先他是構建在Tcp/Ip協議之上,效率相對於tcp要低,傳輸字節也要比tcp多,因此他傳輸佔用的時間會長,固然咱們也能使用一些gzip數據壓縮等對數據壓縮或者相似於Hessain,Thrift等等傳輸2進制數據流,減小數據傳輸量縮減與TCP的差距,固然HTTP也是有不少本身的優勢,好比他的存在天生就能夠解決異構調用的問題,還有處理處理大流量高併發的狀況下不少成熟開源的解決方案想iis,nginx,tomcat,apache等。

因此對上面兩種協議的對比,各有所長各有其短,你們各取所需就好啦。

各類數據序列化對比

數據傳輸協議的取捨,也是根據本身的需求,在.net的世界中我認爲應該json跟xml應該是被你們普遍使用的。那麼還有那些對象序列化常見於網絡傳輸呢,Hessian,thrift也是比較經常使用的。網上也有不少對比,我從網上拿下來的就有,其實以下圖,僅供參考。

.Net使用Hessian進行序列化,實現基於Http協議的RPC

針對上述的測試圖,咱們能夠看出Hessian也是一個不錯的選擇,那麼在這裏我來寫一個.Net mvc中使用hessian的小例子,供你們學習參考,也體驗下RPC風格的Hessian有多便捷。

同時hessian也支持N多語言,他採用二進制格式傳輸的服務框架,據測試效率是soap傳輸的10倍。因此更輕量快速,官網地址:http://hessian.caucho.com/

那麼咱們摒棄類微軟的webservice,wcf,webapi等框架,使用啦開源的hessian,來實施服務之間的遠程調用。

一、服務端

引用Hessiancsharp.dll

實現類繼承CHessianHandler類,引用命名空間using hessiancsharp.server,同時實現Iserverice接口,Iservice是對外提供的。

 public class Service : CHessianHandler, IService
    {
        private readonly string _connStr = ConfigurationManager.ConnectionStrings["ConnectionString_write"].ConnectionString;

        #region IService 成員

        public string ServerName { get { return ConfigurationManager.AppSettings["ServerName"]; } }
        public List<D_DriverInfo> GetDriverInfo()
        {
            try
            {
                using (DbConnection conn = new SqlConnection(_connStr))
                {
                    conn.Open();
                    string sql = "SELECT TOP 10 * FROM dbo.D_DriverInfo";

                    return conn.Query<D_DriverInfo>(sql).ToList();
                }
            }
            catch (Exception ex)
            {
                return null;
            }

        }

        public D_DriverInfo GetDriverInfoByUcode(string ucode)
        {
            try
            {
                using (DbConnection conn = new SqlConnection(_connStr))
                {
                    conn.Open();
                    string sql = "SELECT * FROM dbo.D_DriverInfo where Ucode = @Ucode";

                    return conn.QuerySingle<D_DriverInfo>(sql, new { Ucode = ucode });
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        #endregion
    }
View Code
 public interface IService
    {
        string ServerName { get;  }
        List<D_DriverInfo> GetDriverInfo();
        D_DriverInfo GetDriverInfoByUcode(string ucode);
    }
 <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
    <httpHandlers>
      <add verb="*" path="HessianServiceMvc.IService.hessian" type="HessianServiceMvc.Service, HessianServiceMvc" />
    </httpHandlers>
  </system.web>
   <system.webServer>
        <handlers>        
            <add name="MvcHessianService" path="*.hessian" verb="*" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
        </handlers>
    </system.webServer>
public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{hessian}.hessian/{*pathInfo}");
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                name: "Default",
                url: "{controller}/{action}/{id}",
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
            );
        }      

二、客戶端使用服務

引用Hessiancsharp.dll,把服務端的接口寫下來,不用實現,遠程用服務實現服務調用方的方法。

            CHessianProxyFactory factory = new CHessianProxyFactory();
            string url = "http://172.18.5.61:9020/HessianService.hessian";//修改成你的server端地址
            IService test = (IService)factory.Create(typeof(IService), url);
            object result = test.GetDriverInfo();
            List<D_DriverInfo> s = HClient.RunClient<IService>().GetDriverInfo();
            return Json(s, JsonRequestBehavior.AllowGet);

Note,不妨試試,感覺下使用起來方便快捷不?

說說服務路由,服務負載均衡與服務去中心化結構

首先若是你的業務量不是很大,服務都是單臺部署,那麼你的服務地址能夠硬編碼到你的項目中,可是若是你的服務單臺扛不住流量併發甚至性能特別差,那麼咱們就須要分佈式部署咱們的服務。

最初咱們是這樣子實現的

不論你走的是老式的Esb,仍是一些代理服務器,都是先把請求打到另一臺服務器,而後給你轉接給服務提供方。

如今咱們是怎麼實現的呢

Note:Soa架構會提供一個Client.dll,給到調用方,讓調用方沒必要關係你的傳輸協議怎麼實現,負載算法怎麼實現,這均可以配置出來。而後服務每上線一臺機器,都會自動註冊接口地址等信息到服務配置中心,服務監測系統也會及時的捕捉到各個服務的上下線狀態,而後更新存儲起來,Client內置有負載均衡及緩存功能,根據監測系統提供的數據,客戶端配置的信息,本身發現最優的服務給到客戶端。然而這一切都放生在客戶端。沒有第三方代理服務器出現。

由上述兩張圖片,也能夠得出一個信息,咱們先假定使用圖一,若是代理服務器或是請求路由分發器之類的東西掛了,那全部的服務就不能用啦,還有中間轉接一次,性能也不如第二種好,第二種沒有中心化結構,我感受仍是挺叼的,不寫了,這篇就到這裏吧。

總結

比較淺,也比較籠統,若是有什麼不妥之處,還望提出,同時也歡迎加入左上方羣,咱們一塊兒交流學習。

相關文章
相關標籤/搜索