天天看點

三十、【C#.Net開發架構】WCFHosting服務主機的利用WCF服務通訊和實作思路

 回《【開源】EFW架構系列文章索引》       

 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.總結

       WCFHosting程式隻是一個WCF自托管宿主,當然你可以修改此程式讓WCF服務托管在IIS或Windows Services中,WCFHosting程式隻有三個核心功能:WCFHandlerService服務用來實作用戶端與服務端通訊,RemoteLoader用來實作通路對應的服務端控制器程式,Router服務用來實作中間件的連接配接路由和負載均衡。

三十、【C#.Net開發架構】WCFHosting服務主機的利用WCF服務通訊和實作思路

源代碼項目解決方案目錄:

三十、【C#.Net開發架構】WCFHosting服務主機的利用WCF服務通訊和實作思路

WCFHosting程式界面

三十、【C#.Net開發架構】WCFHosting服務主機的利用WCF服務通訊和實作思路

配置檔案說明,包括用戶端的App.Config和服務端的App.Config兩個配置檔案

1)用戶端的App.Config

主要是ClientType參數和WCF_endpoint參數的設定,ClientType必須設定為WCFClient,WCF_endpoint設定為WCF位址;

三十、【C#.Net開發架構】WCFHosting服務主機的利用WCF服務通訊和實作思路

2)服務端的App.Config

三十、【C#.Net開發架構】WCFHosting服務主機的利用WCF服務通訊和實作思路

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服務,中間件路由功能及負載均衡實作

問題一:由于網絡中斷問題等問題引起通訊錯誤,再恢複之後必須可以繼續使用,不需要關閉系統重新登入系統;再就是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 { }
        }      

問題二,必須解決中間件能夠把緩存的用戶端資訊進行持久化,重新啟動中間件又能加載非正常退出的用戶端資訊;

       WCF中間件基本功能都已具備,實作了用戶端與服務端的通訊,實作服務端分布式部署與負載均衡。但中間件還是非常簡陋的,如持久化用戶端連接配接資料、更加靈活的負載均衡算法等還有許多功能需要不斷完善。中間件路由與負載均衡的實作下一章詳細講解。