EFW框架源代碼下載V1.3:http://pan.baidu.com/s/1c0dADO0
EFW框架實例源代碼下載:http://pan.baidu.com/s/1eQCc69G
前言:以前的系統都是直接客戶端直連數據庫服務器,后來考慮到服務器的安全性、數據庫連接數的限制、分布能力差等問題,特別是那幾年中間件、SOA、ESB等炒得比較火,為了跟上時代腳本有必要開發一個中間件,把后台邏輯業務在中間件中運行。剛開始考慮過WebServices,但是需要部署在IIS中,還有性能問題都比較嚴重,試了一下效果不是很好,后來覺得WCF不錯,但一直沒有找到好的方式怎么與現有的架構結合,如果把業務代碼全改寫成WCF服務方式提供給客戶端調用,感覺工作量很大,光看着WCF那些配置文件就頭大,特別是破壞了現有程序架構,這樣使用WCF對現有框架也沒什么意義。后來在完善Web版框架中從HttpHandlers中找到了思路,發現沒有必要把業務功能做成WCF服務,而WCF服務只是用來實現客戶端與后台業務的通訊,這樣中間件只需要一個WCF服務用來連接客戶端控制器與服務端控制器,把Winform版控制器層也分拆成wcfclientController與wcfController。這樣原來的程序結構基本沒變,保證了Web版、Winform版、WCF版三種類型系統的程序架構,編碼風格等都一致,讓EFW框架全面支持多種系統開發;
本文要點:
1.WCFHosting服務主機介紹
2.WCFHosting服務主機實現
3.WCFHosting服務主機必須解決的兩個問題
4.總結
1.WCFHosting服務主機介紹
WCFHosting程序只是一個WCF自托管宿主,當然你可以修改此程序讓WCF服務托管在IIS或Windows Services中,WCFHosting程序只有三個核心功能:WCFHandlerService服務用來實現客戶端與服務端通訊,RemoteLoader用來實現訪問對應的服務端控制器程序,Router服務用來實現中間件的連接路由和負載均衡。
源代碼項目解決方案目錄:
WCFHosting程序界面
配置文件說明,包括客戶端的App.Config和服務端的App.Config兩個配置文件
1)客戶端的App.Config
主要是ClientType參數和WCF_endpoint參數的設置,ClientType必須設置為WCFClient,WCF_endpoint設置為WCF地址;
2)服務端的App.Config
2.WCFHosting服務主機實現
1)FrmHosting.cs界面,啟動、停止WCF服務
啟動的時候可以根據設置里的配置開啟相應功能,比如:
顯示調試信息,那么每個客戶端每次與服務端交互的內容都會在日志界面顯示出來
開啟WCF服務,如果此主機是作為系統的中間件那么必須勾上此處
開啟路由服務,如果此主機設置為路由器那么必須勾上此處
開啟心跳檢測,正式使用的系統必須勾上次處,如果是開發階段的時候可以不勾,便於調試程序
2)WCFHandlerService服務,客戶端通過調用此wcf服務連接、執行、斷開與中間件通訊
WCFHandlerService服務的IapiWCFHandlerService契約使用了CallbackContract回調操作,這樣實現了客戶端與服務端之間雙向通訊,服務端可以主動向客戶端發送數據,這是Web程序沒有的功能,Web程序只能通過定時訪問來實現此功能。
WCFHandlerService服務對象有5個核心方法,
CreateDomain:打開客戶端(EFWWin.exe程序)會調用此方法在服務端創建在線用戶
ProcessRequest:客戶端調用此方法訪問服務端控制器代碼
UnDomain:客戶端(EFWWin.exe程序)退出前調用此方法清除服務端在線用戶
Heartbeat:客戶端像心跳一樣,調用此方法定時向服務端發送在線狀態
SendBroadcast:服務端向客戶端發送消息
3)Loader對象,管理每個連接的客戶端,並通過反射調用wcf控制器
4)BaseWCFClientController客戶端控制器基類
5)BaseWCFController服務端控制器基類
6)JsonWCFController客戶端與服務端數據交換基於Json字符串格式
7)Router服務,中間件路由功能及負載均衡實現
3.WCFHosting服務主機必須解決的兩個問題
問題一:由於網絡中斷問題等問題引起通訊錯誤,再恢復之后必須可以繼續使用,不需要關閉系統重新登錄系統;再就是wcf服務器主機必須反饋此客戶機是斷開狀態;
問題二:由於WCF主機異常奔潰,再重啟后能重新接管以前連接到此主機的所有客戶端連接;不需要客戶端退出系統重新啟動;
解決問題的辦法:
問題一,增加心跳機制,讓客戶端定時向wcf主機發送一條消息,如果超時沒有接收到就證明客戶端斷開了連接;解決網絡中斷客戶端自動重連服務端,首先客戶端設置為取消服務器憑據認證,再就是客戶端調用重連方法;
<netTcpBinding> <binding name="netTcpExpenseService_ForSupplier" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="10" maxReceivedMessageSize="2147483647"> <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" /> <security mode="None"> <transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" /> <message clientCredentialType="Windows" /> </security> </binding> </netTcpBinding>
/// <summary> /// 重新連接wcf服務 /// </summary> /// <param name="mainfrm"></param> public static void ReConnectionWCFService(IClientService mainfrm) { try { NetTcpBinding binding = new NetTcpBinding("NetTcpBinding_WCFHandlerService"); //binding.OpenTimeout = TimeSpan.FromSeconds(10); //binding.TransferMode = TransferMode.Buffered; DuplexChannelFactory<IapiWCFHandlerService> mChannelFactory = new DuplexChannelFactory<IapiWCFHandlerService>(mainfrm, binding, System.Configuration.ConfigurationSettings.AppSettings["WCF_endpoint"]); IapiWCFHandlerService wcfHandlerService = mChannelFactory.CreateChannel(); using (var scope = new OperationContextScope(wcfHandlerService as IContextChannel)) { var router = System.ServiceModel.Channels.MessageHeader.CreateHeader("routerID", myNamespace, AppGlobal.cache.GetData("routerID").ToString()); OperationContext.Current.OutgoingMessageHeaders.Add(router); wcfHandlerService.Heartbeat(AppGlobal.cache.GetData("WCFClientID").ToString()); } if (AppGlobal.cache.Contains("WCFService")) AppGlobal.cache.Remove("WCFService"); AppGlobal.cache.Add("WCFService", wcfHandlerService); //開啟發送心跳 //if (timer == null) // StartSendWCFHeartbeat(); //else // timer.Start(); } catch { } }
問題二,必須解決中間件能夠把緩存的客戶端信息進行持久化,重新啟動中間件又能加載非正常退出的客戶端信息;
4.總結
WCF中間件基本功能都已具備,實現了客戶端與服務端的通訊,實現服務端分布式部署與負載均衡。但中間件還是非常簡陋的,如持久化客戶端連接數據、更加靈活的負載均衡算法等還有許多功能需要不斷完善。中間件路由與負載均衡的實現下一章詳細講解。