消息智能路由組件SmartRoute


         消息傳遞在軟件開發過程中是一件很常見的事情,而在不同的場景所使用消息傳遞方式也有所不同,在對象之間制定相關接口方法和對象結構,對於進程之間可能使用內存共享或一些通訊產品,在不同服務器之的消息通訊則使用一些通訊產品(MQ)或構建滿足自己的RPC通訊機制.不同場景技術人員都要掌握不同的技術方法來實現,由於應用技術和差異性容易導致開發成本和維護成本的上漲,為了解決這一系列的問題在這段時候思考后實現一種統一的消息傳遞方式,而這種應用方式不管是對象間,進程或服務器在應用上都不會任何差,在這里稱這技術為消息智能路由(為了快速驗證想法,大概花了一周的業余時間制定了一個可用的原型).

SmartRoute可實現場景

 

如何智能?

         SmartRoute是依據訂閱者的ID來進行消息發送傳遞,類似於郵件地址一樣;只要在訂閱的時候制定相應的接收實現即可接收投遞到這一ID的消息.然而這方式非常普通並沒有什么所謂智能高大上在這里.其實SmartRoute的智能優點在於技術人員完全不用去關心訂閱者所在的位置,不管是當前程序,其他應用程序還是其他服務器,SmartRoute都可以自動地幫你投遞過去.最重要的是技術人員完全不用配置任何環境和安裝任何中間服務,只需要在程序中加載SmartRoute這系列的工作都可以自動完成(沒錯,即使你是跨服務器投遞消息也不需要做額外的配置和安裝中間服務器);每個SmartRoute實例除承擔着接收和投遞工作的同時也承擔了消息路由的角色;不同進程和不同服務器運行的SmartRoute實例會自動組建集群(而這個自動構建也不需要配置或安裝服務)

Hello應用

         一個組件的易用性才能體現它的價值,所以在設計SmartRoute的時候就遵循一個原則,在應用中盡量做到不需要配置即可用.以下通過通過簡單的Hello程序來描述一下組件設計的易用性.

l  HelloRequest

class Request : ISubscribeHandler
    {
        public Request()
        {
            Route.Subscribe("Ken", this);
        }

        public DateTime CreateTime
        {
            get;
            set;
        }

        public void Say(string name)
        {
            Hello hello = new Hello { Name ="hello "+ name };
            hello.SendTo(s => s.From("Ken"), "henry");
        }

        public ILogHandler Log
        {
            get;
            set;
        }

        public void Process(INode node, IMessage message)
        {
            Hello hello = message.GetBody<Hello>();
            Console.WriteLine("{0} Request  receive:{1}",DateTime.Now, hello.Name);
        }
    }

l  HelloReqponse

class Response : ISubscribeHandler
    {
        public Response()
        {
            Route.Subscribe("henry", this);
        }
        public DateTime CreateTime
        {
            get;
            set;
        }

        public ILogHandler Log
        {
            get;
            set;
        }

        public void Process(INode node, IMessage message)
        {
            Hello hello = message.GetBody<Hello>();
            Console.WriteLine("{0} response receive:{1}",DateTime.Now, hello.Name);
            hello.Name = "hello " + message.Sender;
            hello.SendTo(message.Sender);
        }
    }

Request和Response各自訂閱了信息,通過實現ISubscribeHandler來接收投遞過來的消息.可以通過運行以下代碼來測試訂閱的有效性.

class Program
    {
        static Request request;
        static Response response;
        static void Main(string[] args)
        {
            request = new Request();
            response = new Response();
            while (true)
            {
                request.Say("henry");
                System.Threading.Thread.Sleep(3000);
            }
        }
    }

l  運行結果

擴展進程間通訊

         對於SmartRoute對現有的訂閱進行跨進程訪問則是一件非常簡單的事件,並不需要修改或配置任何代碼即可完成.下面分別建兩個程序分別引用HelloRequest和HelloResponse

l  HelloRequestApp

class Program
    {
        static Request request;
        static void Main(string[] args)
        {
          
            request = new Request();
            while (true)
            {
                request.Say("henry");
                System.Threading.Thread.Sleep(3000);
            }
        }
    }

l  HelloResponseApp

class Program
    {
      
        static Response response;
        static void Main(string[] args)
        {
           
            response = new Response();
            System.Threading.Thread.Sleep(-1);
        }
    }

l  運行結果

服務器間通訊

         SmartRoute在同一個局域網內會自動發現和組建路由,所以在不調整任何設計和代碼的情況下,只需要把兩個應用部署在不同服務器就可以進行信息訂閱和發送.

技術要點

l  通信功能

除了本進程內訂閱和轉發不需要涉及到通訊外,進程和服務器間都需要通訊服務.所以做這樣一個功能需要點通訊技術經驗,不過現在成熟的開發的通訊庫也有不少可以直接拿來用.

l  節點發現和握手

組件的靈活之處就是不需要任何配置就能實現交互,所以每個節點都具備發其他節點的能力;為了滿足這一需求需要使用UDP廣播技術,每個節點都會把自己的服務信息廣播出去,當其他節點接收到這些信息后就創建握手連接.

l  同步訂閱信息

由於在設計的過程中強調沒有數據中心點,就是整個集群里的所有節點都是相互直連的.所以每個節點的訂閱信息都會同步到不同節點上,這樣才能保證消息投遞的有效性.為了保證訂閱的有效性同樣訂閱取的時候需要告訴其他節點變更情況.

l  制定訂閱規則

訂閱在接收消息處理的情況是多樣性的,有可能是操作數據庫,HTTP或者網絡轉發;所以需要給訂閱制定規划,讓使用者可以實現不同的訂閱處理.

以下是一個簡單網絡轉發訂閱

    public class TCPSubscribeHandler : ISubscribeHandler
    {
        public ILogHandler Log { get; set; }

        public IChannel Channel
        {
            get;
            set;
        }

        public void Process(INode node, IMessage message)
        {
            Channel.Server.Send(message,Channel);
        }

        public DateTime CreateTime
        {
            get;
            set;
        }
    }

下載DEMO


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM