1. 程式人生 > >基於Redis訊息的訂閱釋出應用場景

基於Redis訊息的訂閱釋出應用場景

目錄

  • 基於Redis訊息的訂閱釋出應用場景
  • 1.應用背景
  • 2.困境
    • 2.1 鎖表風險
    • 2.2 實時性差
    • 2.3 增加程式設計複雜性
    • 2.4 實時效果
  • 3.解決方案
    • 3.1 前端傳值給服務端
    • 3.2 服務端通過訊息傳給採集控制端
  • 4.詳細程式碼設計
    • 4.1 CSRedisCore
    • 4.2 介面設計如下
    • 4.3 介面實現如下
    • 4.4 實現層程式碼設計
    • 4.5 ConfigureServices中依賴注入
  • 5.效果
    • 5.1 開啟風扇按鈕
    • 5.2 RedisDesktopManager工具中觀察
    • 5.3 觀察web頻道輸出資訊
    • 5.4 觀察實際風扇效果

基於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客戶端物件
        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 實現層程式碼設計

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

4.5 ConfigureServices中依賴注入

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


5.效果

5.1 開啟風扇按鈕

5.2 RedisDesktopManager工具中觀察

在RedisDesktopManager的命令列視窗中輸入PSUBSCRIBE web,進行訂閱web頻道,如下

5.3 觀察web頻道輸出資訊

在前端控制了風扇開啟操作之後如5.1,在RedisDesktopManager觀察web頻道輸出資訊

5.4 觀察實際風扇效果

風扇實時開啟。