目录

* 基于Redis消息的订阅发布应用场景
<https://www.cnblogs.com/JerryMouseLi/p/11012839.html#基于redis消息的订阅发布应用场景>
* 1.应用背景 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#应用背景>
* 2.困境 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#困境>
* 2.1 锁表风险 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#锁表风险>
* 2.2 实时性差 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#实时性差>
* 2.3 增加编程复杂性 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#增加编程复杂性>
* 2.4 实时效果 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#实时效果>
* 3.解决方案 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#解决方案>
* 3.1 前端传值给服务端 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#前端传值给服务端>
* 3.2 服务端通过消息传给采集控制端
<https://www.cnblogs.com/JerryMouseLi/p/11012839.html#服务端通过消息传给采集控制端>
* 4.详细代码设计 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#详细代码设计>
* 4.1 CSRedisCore
<https://www.cnblogs.com/JerryMouseLi/p/11012839.html#csrediscore>
* 4.2 接口设计如下 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#接口设计如下>
* 4.3 接口实现如下 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#接口实现如下>
* 4.4 ConfigureServices中依赖注入
<https://www.cnblogs.com/JerryMouseLi/p/11012839.html#configureservices中依赖注入>
* 4.5 创建一个RedisMQ的消息对象
<https://www.cnblogs.com/JerryMouseLi/p/11012839.html#创建一个redismq的消息对象>
* 4.6 实现层代码设计 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#实现层代码设计>
* 5.效果 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#效果>
* 5.1 打开风扇按钮 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#打开风扇按钮>
* 5.2 RedisDesktopManager工具中观察
<https://www.cnblogs.com/JerryMouseLi/p/11012839.html#redisdesktopmanager工具中观察>
* 5.3 观察web频道输出信息
<https://www.cnblogs.com/JerryMouseLi/p/11012839.html#观察web频道输出信息>
* 5.4 观察实际风扇效果 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#观察实际风扇效果>
* 6 框架图 <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#框架图>
* 7 GitHub <https://www.cnblogs.com/JerryMouseLi/p/11012839.html#github>
基于Redis消息的订阅发布应用场景

1.应用背景


在物联网采集管控系统中,前后端隔离的情况下,前端通过表单(比如按钮,开关,表格等)输入数据到数据库(比如MySql,通过WEBAPI服务端输入),然后采集控制端到数据库里去扫表取数据,将数据下发给物联网络中的终端设备(比如风扇控制板),从而来控制风扇的开跟关。




2.困境

采集控制端需要到数据库中去扫表。这个扫表操作会带来几个问题:

2.1 锁表风险

扫表会有锁表风险,当该DBContext被占用的时候,其他线程不能实时使用此DBContext。

2.2 实时性差


在物联网系统中,数据会非常多,比如有10000台设备,每台设备有100个采集控制点,则控制点最多可能会达到100W数据,这样去扫表,不仅占用DBContext上下文的时间会很长,而且实时性会很差。

2.3 增加编程复杂性

增加了采集服务端编程的复杂性。

2.4 实时效果

用户体验效果较差:客户点了开关控制风扇打开,然后底端设备需要很长时间才能真正打开。




3.解决方案

使用消息订阅发布方法。RabbitMQ比较重,故这里选用Redis的订阅发布功能,而且很多情况下Redis已经被作为缓存在引用,详见如下。

3.1 前端传值给服务端

前端将实时控制值以Restful
API形式通过IP地址端口号+路由(比如:192.168.2.106:5000/ControlConfig)将此值传递给服务端。

3.2 服务端通过消息传给采集控制端


这里通过nuget获得CSRedisCore,来操作Redis的订阅发布功能。采集控制端订阅消息。服务端发布消息。这样操作达到了如下目的:2.1不用经过数据库消息的实时传递;2.2
实时性好;2.3 编程也简单;2.4 实时效果好。




4.详细代码设计

4.1 CSRedisCore

CSRedis 是 redis.io 官方推荐库,支持 redis-trib集群、哨兵、私有分区与连接池管理技术,简易 RedisHelper 静态类。
https://www.nuget.org/packages/CSRedisCore/
<https://www.nuget.org/packages/CSRedisCore/>
通过Nuget获得CSRedisCore库

4.2 接口设计如下

详细说明参考注释。
using CSRedis; namespace IBMS.Infrastruct.Redis { public interface IRedisMQ {
//连接Redis CSRedisClient ConnectCSRedis(); //订阅频道 void SubscribeCSRedis(string
ChannelName); //把message异步发布Redis的频道 void PublishAsyncCSRedis(string channel,
string message); //释放Redis void DisposeCSRedis(); //订阅接受下来的msg的方法 void
Rcv(string Msg, string channel); } }
4.3 接口实现如下

详细说明见注释
using System; using CSRedis; using IBMS.Infrastruct.Appsetting; namespace
IBMS.Infrastruct.Redis { public class RedisMQ : IRedisMQ { //读取连接Redis字符串
private readonly string connectRedis = Appsettings.app(new string[] {
"AppSettings", "RedisCaching", "ConnectionString" });//按照层级的顺序,依次写出来
//定义一个Redis客户端对象 CSRedisClient _RedisMQ; //连接Redis public CSRedisClient
ConnectCSRedis() { return _RedisMQ = new CSRedisClient(connectRedis); }
//释放Redis public void DisposeCSRedis() { _RedisMQ.Dispose(); }
//异步发布消息到Redis的某个频道 public void PublishAsyncCSRedis(string channelName, string
message) { _RedisMQ.PublishAsync(channelName, message); }
//如果自己需要用消息值,需要想方法返回数据 //订阅消息的处理方法 public void Rcv(string channel, string Msg)
{
Console.WriteLine($"{DateTime.Now.ToLongDateString()}|Rcv:{channel},Msg:{Msg}");
} //订阅消息 public void SubscribeCSRedis(string ChannelName) {
_RedisMQ.Subscribe((ChannelName, msg => Rcv(msg.Channel, msg.Body))); } } }
4.4 ConfigureServices中依赖注入

在Startup.cs中的ConfigureServices方法进行依赖注入,如下。
services.AddScoped<IRedisMQ, RedisMQ>();

4.5 创建一个RedisMQ的消息对象


在Controller里定义创建一个消息对象,这一步的前提是需要依赖注入,依赖注入在某种意义上跟C语言的typedef有点像,将typedef会将控制权交给编译器,编译器定义新类型,然后程序运行之后就可以就可以随意通过新类型来定义对象。
IRedisMQ _RedisMQ =new RedisMQ();

4.6 实现层代码设计
// PUT: api/ControlConfig/5 [HttpPut] public async Task Update([FromBody]
ControlConfig ControlConfig) { _RedisMQ.ConnectCSRedis();
_RedisMQ.SubscribeCSRedis("web"); _RedisMQ.PublishAsyncCSRedis("web", $"add
at{DateTime.Now}"); _RedisMQ.PublishAsyncCSRedis("web",
$"{SerializeHelper.Serialize(ControlConfig)}"); Console.ReadKey();
_RedisMQ.DisposeCSRedis(); }
5.效果

5.1 打开风扇按钮



5.2 RedisDesktopManager工具中观察

在RedisDesktopManager的命令行窗口中输入PSUBSCRIBE web,进行订阅web频道,如下


5.3 观察web频道输出信息

在前端控制了风扇打开操作之后如5.1,在RedisDesktopManager观察web频道输出信息


5.4 观察实际风扇效果

风扇实时打开。
备注:采集控制端跟设备端是基于TCP长连接组网方式,协议用的是基于MODBUS的变种,比如加入我们自己的包头包尾包类型等信息,这里不做展开




6 框架图

补上一张框架图,拖到浏览器新窗口,点击放大即可清晰浏览,采用亿图制作,以便更好理解。


7 GitHub

Demo地址:
https://github.com/JerryMouseLi/RedisMQDemo.git
<https://github.com/JerryMouseLi/RedisMQDemo.git>

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信