基于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/

通过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客户端对象
static CSRedisClient _RedisMQ;
//连接Redis
public CSRedisClient ConnectCSRedis()
{
//如果已经连接实例,直接返回
if (_RedisMQ != null)
{
return _RedisMQ;
}
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

基于Redis消息的订阅发布应用场景的更多相关文章

  1. redis基础之订阅发布、主从复制和事务(四)

    前面已经学习了redis的基本的命令行操作和数据类型,下面开始redis一些有趣的功能. 订阅和发布机制 定义:发布者相当于电台,订阅者相当于客户端,客户端发到频道的消息,将会被推送到所有订阅此频道的 ...

  2. python学习之-- redis模块管道/订阅发布

    redis 模块操作剩余其他常用操作 delete(*names):删除任意的数据类型exists(name):检测redis的name是否存在keys(pattern='*'):根据模型获取redi ...

  3. redis 消息队列(发布订阅)、持久化(RDB、AOF)、集群(cluster)

    一:订阅: 192.168.10.205:6379> SUBSCRIBE test Reading messages... (press Ctrl-C to quit) 1) "sub ...

  4. SpringBoot使用JMS(activeMQ)的两种方式 队列消息、订阅/发布

    刚好最近同事问我activemq的问题刚接触所以分不清,前段时间刚好项目中有用到,所以稍微整理了一下,仅用于使用 1.下载ActiveMQ 地址:http://activemq.apache.org/ ...

  5. python 实现redis订阅发布功能

    redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set ...

  6. 【分布式架构】--- 基于Redis组件的特性,实现一个分布式限流

    分布式---基于Redis进行接口IP限流 场景 为了防止我们的接口被人恶意访问,比如有人通过JMeter工具频繁访问我们的接口,导致接口响应变慢甚至崩溃,所以我们需要对一些特定的接口进行IP限流,即 ...

  7. 基于Redis的消息订阅/发布

    在工业生产设计中,我们往往需要实现一个基于消息订阅的模式,用来对非定时的的消息进行监听订阅. 这种设计模式在 总线设计模式中得到体现.微软以前的WCF中实现了服务总线 ServiceBus的设计模式. ...

  8. 基于redis的消息订阅与发布

    Redis 的 SUBSCRIBE 命令可以让客户端订阅任意数量的频道, 每当有新信息发送到被订阅的频道时, 信息就会被发送给所有订阅指定频道的客户端. 作为例子, 下图展示了频道 channel1  ...

  9. 分布式消息总线,基于.NET Socket Tcp的发布-订阅框架之离线支持,附代码下载

    一.分布式消息总线以及基于Socket的实现 在前面的分享一个分布式消息总线,基于.NET Socket Tcp的发布-订阅框架,附代码下载一文之中给大家分享和介绍了一个极其简单也非常容易上的基于.N ...

随机推荐

  1. DRF Django REST framework APIView(一)

    什么是REST? REST是一个标准,一种规范,遵循REST风格可以使开发的接口通用,便于调用者理解接口的作用. 使url更容易理解,让增删改清晰易懂,在前后端分离开发中按照这一规范能加快开发效率,减 ...

  2. css3学习——一列固定宽度且居中

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  3. 大型情感剧集Selenium:4_老中医教你(单/多/下拉框)选项定位 #华为云·寻找黑马程序员#

    今天讲什么 讲什么标题说了,讲selenium的单选.多选.下拉框选项定位.但其实这东西,没什么太多说的,又比较枯燥,那该怎么让这一集selenium的课程变得有趣呢?有请老中医,哈哈- 怎么样,这个 ...

  4. 大规模机器学习在LinkedIn预测模型中的应用实践

    预测模型在 LinkedIn 的产品中被广泛应用,如 Feed.广告.工作推荐.邮件营销.用户搜索等.这些模型在提升用户体验时起到了重要的作用.为了满足建模需求,LinkedIn 开发并且开源了 Ph ...

  5. Prometheus笔记(二)监控go项目实时给grafana展示

    欢迎加入go语言学习交流群 636728449 Prometheus笔记(二)监控go项目实时给grafana展示 Prometheus笔记(一)metric type 文章目录 一.promethe ...

  6. solr集群与项目实战

    什么是 SolrCloud : SolrCloud(solr 云)是 Solr 提供的分布式搜索方案,当你需要大规模,容错,分布式索引和检索能力时使用 SolrCloud.当一个系统的索引数据量少的时 ...

  7. variable fonts - 更小更灵活的字体

    原文链接 variable fonts(下文中vf为缩写)是数字时代制作的字体技术,用更小的文件大小在web上提供更丰富的排版,但是一项新的技术往往伴随着新的挑战和复杂未知的情况.不过,我们要拥抱技术 ...

  8. HDU5470 Typewriter (SAM+单调队列优化DP)

    Typewriter Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Tota ...

  9. CoderForces-913-C

    A New Year party is not a New Year party without lemonade! As usual, you are expecting a lot of gues ...

  10. 深入理解JVM:元空间大小详细解析

    前言 JVM加载类的时候,需要记录类的元数据,这些数据会保存在一个单独的内存区域内,在Java 7里,这个空间被称为永久代(Permgen),在Java 8里,使用元空间(Metaspace)代替了永 ...