序言 在.Net的世界中,一提及SOA,大家想到的應該是Web Service,WCF,還有人或許也會在.NET MVC中的Web API上做上標記,然後泛泛其談! 的確,微軟的這些技術也確實推動著面向服務的世界發展,當然除了微軟還有很多面向服務的開源技術,甚至在某些方面比微軟做的更加優秀。那麼什麼 ...
序言
在.Net的世界中,一提及SOA,大家想到的應該是Web Service,WCF,還有人或許也會在.NET MVC中的Web API上做上標記,然後泛泛其談!
的確,微軟的這些技術也確實推動著面向服務的世界發展,當然除了微軟還有很多面向服務的開源技術,甚至在某些方面比微軟做的更加優秀。那麼什麼是面向服務,面向服務的存在是為瞭解決什麼問題呢?
說說SOA面向服務
SOA是由Garnter在1996年提出的一個概念,旨在讓軟體變的有彈性,能夠迅速響應業務的需求,實現實時企業。基本理念是讓所有信息系統中需要整合的業務使用服務和介面聯繫起來,介面中立,與開發平臺和編程語言無關。這也使得異構信息系統變的可開發,“信息孤島”,重覆造輪子等問題在SOA的體系架構下不攻自破。
簡單通俗的說就是,SOA是不同業務建立不同的服務,服務之間的可以數據交互粗粒度的服務介面分級,這樣鬆散耦合提高服務的重用性,也讓業務邏輯變的可組合,並且每個服務可以根據使用情況做出合理的分散式部署,從而讓服務變的規範,高性能,高可用。
那麼接下來我們首先來看下微軟在這方面做啦哪些貢獻,以及軟體開發是怎樣的一個變化歷程。
代碼復用技術的發展
面向過程(應用內/過程級復用)---->面向對象(應用內/類級復用)--->面向組件(應用內/組件級復用)--->分散式組件(應用間/組件級復用)---->面向服務(應用間/服務級復用)
微軟面向服務提供的技術
那麼針對上面的一張圖,做一個簡短的說明,首先是Tcp與Http協議的比較,這兩個協議各有所長:
基於TCP協議:能夠減少網路傳輸位元組數,降低網路開銷,效率高,但是實現複雜,且由於協議和標準不同,難以進行跨平臺,和企業間的便捷通信,並且當服務越來越多的時候,負載聚恆策略,服務地址管理和配置都會變得複雜和繁瑣,目前也沒有很好的開源支持。
基於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,來實施服務之間的遠程調用。
1、服務端
引用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 } ); }
2、客戶端使用服務
引用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內置有負載均衡及緩存功能,根據監測系統提供的數據,客戶端配置的信息,自己發現最優的服務給到客戶端。然而這一切都放生在客戶端。沒有第三方代理伺服器出現。
由上述兩張圖片,也可以得出一個信息,我們先假定使用圖一,如果代理伺服器或是請求路由分發器之類的東西掛了,那所有的服務就不能用啦,還有中間轉接一次,性能也不如第二種好,第二種沒有中心化結構,我感覺還是挺叼的,不寫了,這篇就到這裡吧。
總結
比較淺,也比較籠統,如果有什麼不妥之處,還望提出,同時也歡迎加入左上方群,我們一起交流學習。