说到订阅服务通讯一般都会想到基于队列的消息生产和消费模式,这也是在实际应该中比较常用的方式。一般生产者把消息发送到队列服务中心,然后消费者去中心订阅;然而这种方式需要一个消息服务中心,而在这里所说的订阅服务通讯则有点不一样,因为需要更灵活的订阅方式,所以需要去除中心化处理;但去除中心化那则需要考虑的事情想对复杂,最基础的环节就是如何维护生产者和消费者的关系,接下来讲解如何实现这种方式。
中心化通讯方式
由于在应用中一般会使用队列服务作为消息中心,所以生产者和消费并没有直接的关系,一个把消息投递到中心,一个从中心中获取。
去除中心化
去除中心化其实就是生产和消费并不依赖于中心服务,每个生产和消费自身就是一个中心服务,简单地说也不存在生产和消费划分;每个服务充当生产的同时也是消费者。
去除中心后服务之间都可以构建订阅体系,即其中一个服务故障也不会影响其他订阅服务,这样在可靠性和灵活性上对于中心化服务都有着很大的优势;但有一个很明显的问题就是没有中心服务,服务之间是如何发现对方呢,这的确是一个麻烦的事情。
如何发现服务
对于不同服务通讯需要做的事情是发现对方,一般的服务程序都有固定的地方(域名)和端口来告诉使用者,你可以通过这个地方connect进来。既然需要去除中心化那自然就不会知道现在有什么服务,所以需要制定一套服务自我发现机制来确保服务间可以自动发现。
既然我们不知道对方的服务地址和端口,那怎样发现对方呢?其实每个服务可以把自己的服务信息通过UDP广播出去,这样其他服务就可以接收到相关的广播,当A接收到其他服务的UDP广播后就会可以知道网内有什么服务,这样就可以向具体的服务发起连接请求,并建立服务与服务之间的通讯。
消费者注册同步
服务和服务之间已经握手了,那消费注册就会变得比较简单,因为消费者随便一台服务上注册都可以同步到同一集群中的所有服务上。
如果消费者在多个服务注册,那整体的通讯结构如下
代码
- 消费者
Route.DefaultNode.Open(); mSwitch = new SubscribeSwitch(); mSwitch.GetServiceSubscribe("HELLO").RegisterProcess<Hello>((o, e) => { e.Reply(e.Data); });
- 生产者
Route.DefaultNode.Open(); mSwitch = new SubscribeSwitch(); Hello hello = new Hello { Name = "hello,how are you?" }; hello = mSwitch.Send<Hello>("HELLO", hello);
在应用代码中不存所有服务地址的概念,只要节点服务打开就会自动向网内进行服务信息广播,并发现网络的其他服务节点。
存在问题
由于UDP广播只能有效于局域网段,不适用于广域网,所以些通讯架构体系也只适用于应用内部的集群通讯体系应用,如果需要应用到广播网,那则需要一个发现中心来确认服务在广域网下是可发现的。