客户端与服务端订阅的介绍
今天主要是结合分布式任务调度模块下消息播报模块的代码,目前市场上比较出名的定于机制有redis机制,下面我们结合redis机制简单先给大家介绍一下订阅和发布。
大家要是想看相关代码请看这里
订阅和发布机制
当一个客户端通过 PUBLISH 命令向订阅者发送信息的时候,我们称这个客户端为发布者(publisher)。
而当一个客户端使用 SUBSCRIBE 或者 PSUBSCRIBE 命令接收信息的时候,我们称这个客户端为订阅者(subscriber)。
为了解耦发布者(publisher)和订阅者(subscriber)之间的关系,Redis 使用了 channel (频道)作为两者的中介 —— 发布者将信息直接发布给 channel ,而 channel 负责将信息发送给适当的订阅者,发布者和订阅者之间没有相互关系,也不知道对方的存在:
知道了机制后,下面我们来看一下实现的原理
客户端和服务端可以理解为都各自维护着一个channel列表。
(1)PUBLISH
当客户端向某个频道发送消息时,Redis首先在结构体redisServer中的pubsub_channels中找出键为该频道的结点,遍历该结点的值,找出所有的客户端,将消息发送给这些客户端。然后,遍历结构体Redis Client中的pubsub_patterns,找出包含该频道的模式的结点,将消息发送给订阅了该模式的客户端。
(2)SUBSCRIBE
首先,在客户端结构体client中,有一个属性为pubsub_channels,该属性表明了该客户端订阅的所有频道,它是一个字典类型,通过哈希表实现,其中的每个元素都包含了一个键值对以及指向下一个元素的指针,每次订阅都要向其中插入一个结点,键表示订阅的频道,值为空。然后,在表示服务器端的结构体redisServer中,也有一个属性为pubsub_channels,但此处它表示的是该服务器端中的所有频道以及订阅了这个频道的客户端,它也是一个字典类型,插入结点时,键表示频道,值则是订阅了这个频道的所有客户端组成的链表。最后Redis通知客户端其订阅成功。
二、REDIS发布订阅和监听REDIS队列的区别
使用jedis的subscribe和publish实现的发布订阅系统 PK 使用jedis的BRPOP和BLPOP实现的阻塞时消息队列
1、redis队列为阻塞队列,获取完一个信息后会主动退出,如果想一直获取信息则需要开启一个监听;而发布订阅中的订阅端是自动完成的监听。
2、redis队列中的数据取出后就消失了,无法满足多端口;而发布订阅可以将数据发布到多个channel。
3、redis队列的数据不取出就会一直在缓存中;而发布订阅中订阅获取的数据不处理就消失了。
下面我们简单看看鸿蒙
在feature的发布订阅文件中,主要功能函数只有 ** OnMessage 和 GetRelation**
这里的并不是只消费者,应该是和服务器端实现订阅的客户端。这两个类型的结构体,第一个就是客户端的信息,用来存放客户端信息,主要是客户端的身份标识,consumer的指针,以及topic的中信息的存放
第二个结构体relation就是消息的一个过渡吧,个人感觉就是topic的封装,用来存放消息中的数据。
这里就是实现feature的类,定义了一个函数指针,讲feature和topic进行关联的一个函数,一个互斥锁,这个主要是为了防止进行相关操作时候数据的变化出现意外情况,所以事先加锁。还有一个就是对feature定义一个标识身份
这里用到了分支结构,对要发布的消息进行处理,这里就是将消息值写进了topic变量进行发布,然后把这个topic和一个广播服务进行关联实现。,仅限是要发布的消息,其他消息不进行处理,其中对身份判断环节实现了发布,基于Notify函数,这个函数应该是和线程有关,这里是处理这个请求,将消息进行广播。
这个函数就是之前处理消息时候讲feature和消息数据topic中消息数据进行关联的函数。
初始化当中提到实例instance函数,对广播服务进行处理
这里初始化时候涉及到了实例特征,如下面结构体。
以上为发布和订阅的再次分析!