消息智能路由组件SmartRoute

         消息传递在软件开发过程当中是一件很常见的事情,而在不一样的场景所使用消息传递方式也有所不一样,在对象之间制定相关接口方法和对象结构,对于进程之间可能使用内存共享或一些通信产品,在不一样服务器之的消息通信则使用一些通信产品(MQ)或构建知足本身的RPC通信机制.不一样场景技术人员都要掌握不一样的技术方法来实现,因为应用技术和差别性容易致使开发成本和维护成本的上涨,为了解决这一系列的问题在这段时候思考后实现一种统一的消息传递方式,而这种应用方式不论是对象间,进程或服务器在应用上都不会任何差,在这里称这技术为消息智能路由(为了快速验证想法,大概花了一周的业余时间制定了一个可用的原型). node

SmartRoute可实现场景

如何智能?

         SmartRoute是依据订阅者的ID来进行消息发送传递,相似于邮件地址同样;只要在订阅的时候制定相应的接收实现便可接收投递到这一ID的消息.然而这方式很是普通并无什么所谓智能高大上在这里.其实SmartRoute的智能优势在于技术人员彻底不用去关心订阅者所在的位置,不论是当前程序,其余应用程序仍是其余服务器,SmartRoute均可以自动地帮你投递过去.最重要的是技术人员彻底不用配置任何环境和安装任何中间服务,只须要在程序中加载SmartRoute这系列的工做均可以自动完成(没错,即便你是跨服务器投递消息也不须要作额外的配置和安装中间服务器);每一个SmartRoute实例除承担着接收和投递工做的同时也承担了消息路由的角色;不一样进程和不一样服务器运行的SmartRoute实例会自动组建集群(而这个自动构建也不须要配置或安装服务) 数据库

Hello应用

         一个组件的易用性才能体现它的价值,因此在设计SmartRoute的时候就遵循一个原则,在应用中尽可能作到不须要配置便可用.如下经过经过简单的Hello程序来描述一下组件设计的易用性. c#

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);
        }
    }

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);
        }
    }

RequestResponse各自订阅了信息,经过实现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  运行结果 this

扩展进程间通信

         对于SmartRoute对现有的订阅进行跨进程访问则是一件很是简单的事件,并不须要修改或配置任何代码便可完成.下面分别建两个程序分别引用HelloRequestHelloResponse spa

HelloRequestApp 设计

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

HelloResponseApp code

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

相关文章
相关标签/搜索