Redis 消息中间件 ServiceStack.Redis 轻量级
问题:
公司开了个新项目,算上我一共3个人。车间里机台通过流水线连通联动的玩意。一个管理控制系统连接各个机台和硬件。专机类型就有5种,个数差不多20个左右。
软件规划的时候采用总分的结构,管理控制系统和专机子系统之间通过消息中间件通讯。本来也想TCP连接来着,但是开发时间不允许。而且每个系统都得写一遍这个玩意。
消息中间件有很多个,比如 Kafka、RabbitMQ、RocketMQ等国内外的消息中间件。这些中间件无论宣称的多么轻量级都要啃一下,更要命的是就他娘三个人。而且后面还要这个鸡儿系统可复制。
考虑到消息及时性、开发难易程度、维护简便性等因素后决定用Redis的pub/sub功能来实现.软件结构大概如类似结构。

可用性:
作为消息通知属于安装了Redis就有的功能,因为Redis是用在系统中存储一些热数据,不用单独维护,在Windows中属于服务直接就开了。
作为可以分布式集群使用的数据库,消息传递应该比较OK了。虽然使用的client-server,但是server-server已经很好了。料想client-server也不会差
试验消息内容发送订阅的情况下,速度在30毫秒内,貌似可以。看其他博主说大于10K入队比较慢,但是可以不用入消息队列啊,用发布订阅。
.net 下一般使用ServiceStack.Redis,要命的是4.0以后收费,可以破解的但是不支持List<T>型的数据直接存取,想用只能变成JSON字符串存着。
- 如果只是用订阅发布功能,不存储热数据或者不使用List<T>的数据可以使用4.0以上的版本。文末会贴上两个类型的下载包。想用其他的包也可以,我这里只说一种思路。
实现:
模块结构图展示如下

public static class MSServer
{
// 定义一个object对象
private static object objinstance = new object(); private static ServerState CurState = ServerState.Free; static PooledRedisClientManager prcm; private static string clientmake = string.Empty; /// <summary>
/// 连接的地址
/// </summary>
/// <param name="IP">地址127.0.0.1:6379</param>
/// <param name="rechannels">接收通道 {"channel:1-13","channel:1-5"}</param>
/// <returns></returns>
public static int OpenServer(string IP ,string[] rechannels)
{
try
{
if (prcm == null)
{
lock (objinstance)
{
if (prcm == null)
{
prcm = CreateManager(IP, IP);
CurState = ServerState.Init;
return CreateLink(rechannels);
}
}
}
}
catch
{
prcm = null;
CurState = ServerState.Free;
return -;
}
return ;
} private static int CreateLink(string[] SourceID)
{
if (CurState == ServerState.Init && SourceID.Length > )
{
try
{
using (IRedisClient Redis = prcm.GetReadOnlyClient())
{
clientmake = SourceID[];
var info = Redis.GetClientsInfo().Where(i => i["name"] == clientmake).ToList();
info.ForEach(i =>
{
Redis.KillClient(i["addr"]);
});
Redis.SetClient(clientmake);
IRedisSubscription sc = Redis.CreateSubscription();
Task.Run(() =>
{
try
{
sc.SubscribeToChannels(SourceID);
}
catch { }
});
sc.OnMessage += new Action<string, string>(showpub);
}
CurState = ServerState.Work;
}
catch
{
string message = string.Empty;
prcm = null;
CurState = ServerState.Free;
return -;
}
return ;
}
else
{
return ;
}
} public static Action<string, string> ReceiveMessage;
static void showpub(string channel, string message)
{
if (ReceiveMessage != null)
{
ReceiveMessage(channel, message);
}
} private static PooledRedisClientManager CreateManager(string writeHost, string readHost)
{
var redisClientConfig = new RedisClientManagerConfig
{
MaxWritePoolSize = ,//“写”链接池链接数
MaxReadPoolSize = ,//“读”链接池链接数
DefaultDb = ,
AutoStart = true,
};
//读的客户端只能接受特定的命令,不能用于发送信息
var RedisClientManager = new PooledRedisClientManager(
new string[] { writeHost }//用于写
, new string[] { readHost }//用于读
, redisClientConfig);
CurState = ServerState.Init; return RedisClientManager;
}
/// <summary>
/// 发送信息
/// </summary>
/// <param name="channel">通讯对象 "channel:1-13"</param>
/// <param name="meesage">发送信息 "test send "</param>
/// <returns>0 发送失败 1 发送成功 -1 连接损毁 检查网络后重建</returns>
public static long PubMessage(string channel, string meesage)
{
if (CurState == ServerState.Work)
{
if (!string.IsNullOrEmpty(channel) && !string.IsNullOrEmpty(meesage))
{
try
{
using (IRedisClient Redis = prcm.GetClient())
{
Redis.SetClient(clientmake);
return Redis.PublishMessage(channel, meesage);
}
}
catch
{
prcm = null;
CurState = ServerState.Free;
return -;
}
}
else
{
return ;
}
}
else
{
return -;
}
}
} public enum ServerState
{
Free,
Init,
Work,
Del
}
有一个问题,就是连接远程的服务器时如果网络断开再重连,会残留没用的client ,这样如果网络断断续续的话,会留好多没有清除的客户端。

这个在3.0.504版本中Redis 中也有这个问题,不知道是基于什么考虑的。所以需要建立连接的时候,给个客户端名称,再初始化的时候删掉所有同类型的名称。
使用的时候大概类似操作 textbox2.text = "channel:1-5" .为了简便发布的和监听的都是本地的一个通道。
private void button1_Click(object sender, EventArgs e)
{ //11.1.7.152 192.168.12.173
int result = ServerMS.MSServer.OpenServer("127.0.0.1:6379", new string[] { textBox2.Text });
label1.Text = result.ToString();
//1匿名事件
ServerMS.MSServer.ReceiveMessage += new Action<string, string>(fuck); if (result == )
{
//发送失败重新发送 检查 通道和字符串后重新发送
}
else if (result == )
{
//发送成功
}
else if (result == -)
{
//连接错误 需要 ServerMS.MSServer.OpenServer("192.168.12.173:6379", new string[] { textBox2.Text });
} } void fuck(string channel, string message)
{
this.BeginInvoke(new Action(() =>
{
textBox4.Text = channel + message;
}));
}
public bool sdfsd = true; private void button3_Click(object sender, EventArgs e)
{long result = ServerMS.MSServer.PubMessage(textBox2.Text, DateTime.Now.ToString("yyyyyMMddhhmmssfff")); if (result == )
{
//发送失败重新发送
}
else if (result == )
{
//发送成功
}
else if (result == -)
{
//连接错误 需要 ServerMS.MSServer.OpenServer("192.168.12.173:6379", new string[] { textBox2.Text });
}
}
为了简便channel:是通道的固定命令 ,可以自定义channel:后面的内容,发送就有反馈。确保所有机台都接收到。
如果有断线的需要程序自己重连,接收通道的客户端不可以再给其他的使用,Redis上说Redis client 进入订阅模式时只能接受订阅发布等命令指令,不接受普通的存取和其他命令
所以如果需要在读取、写入、发布、执行其他的指令需要使用其他客户端,否则就出错了。跑了几天了上亿次的测试貌似没有出现什么问题。

发布订阅消息不会走AOF RDB只存在于内存中,即发即用,用完就没了。没在线就没了。需要考虑使用环境。
还用ping pong来确定连接状态,也可以自定义数据,使用场景要自己开发,要适合自己的才是好的。
下载:
4.0 dll
链接:https://pan.baidu.com/s/1966t0pduHxQXcxcxV3ZTeQ
提取码:js8p
5.8 dll不可以使用List<T>类型
链接:https://pan.baidu.com/s/1RFgY4V0ZO78Wvd7LOxr97g
提取码:bxh2
Redis 消息中间件 ServiceStack.Redis 轻量级的更多相关文章
- Redis客户端ServiceStack.Redis的简单使用
在nuget中下载ServiceStack.Redis,但是运行之后会出现一个问题: Exception: "Com.JinYiWei.Cache.RedisHelper"的类型初 ...
- 关于 ServiceStack.Redis 4.0 License
今天更新了框架中的Redis驱动ServiceStack.Redis,最新版本4.0.5.0. 在做简单压力测试时出现异常,提示每小时允许6000个请求. The free-quota limit o ...
- 『性能』ServiceStack.Redis 和 StackExchange.Redis 性能比较
背景 近来,需要用到 Redis 这类缓存技术 —— MongoDB 和 Redis 没有进行过比较. 我也懒得在这些细节上 纠结那么多 —— 按照网友给出的文章,听从网友建议,选择 Redis. R ...
- servicestack.redis工具类
using System;using System.Collections.Generic;using System.Linq;using ServiceStack.Redis;using Servi ...
- 使用ServiceStack.Redis实现Redis数据读写
原文:使用ServiceStack.Redis实现Redis数据读写 User.cs实体类 public class User { public string Name { get; set; } p ...
- .Net使用Redis详解之ServiceStack.Redis(七)
序言 本篇从.Net如何接入Reis开始,直至.Net对Redis的各种操作,为了方便学习与做为文档的查看,我做一遍注释展现,其中会对list的阻塞功能和事务的运用做二个案例,进行记录学习. Redi ...
- ServiceStack.Redis订阅发布服务的调用(Z)
1.Redis订阅发布介绍Redis订阅发布是一种消息通信模式:发布者(publisher)发送消息,订阅者(Subscriber)接受消息.类似于设计模式中的观察者模式.发布者和订阅者之间使用频 ...
- serviceStack.Redis 在PooledRedisClientManager 中设置密码
ServiceStack.Redis 是一个C#访问Redis的客户端,可以说可以通过它实现所有需要Redis-Cli的功能.但是今天我在主Redis 实例设置了访问密码,而在slave 上没有设置, ...
- ServiceStack.Redis订阅发布服务的调用
1.Redis订阅发布介绍 Redis订阅发布是一种消息通信模式:发布者(publisher)发送消息,订阅者(Subscriber)接受消息.类似于设计模式中的观察者模式. 发布者和订阅者之间使用频 ...
随机推荐
- JVM原理以及深度调优(二)
JVM内存分配 内存分配其实真正来讲是有三种的.但对于JVM来说只有两种 栈内存分配: 大家在调优的过程中会发现有个参数是-Xss 默认是1m,这个内存是栈内存分配, 在工作中会发现栈OutOfMem ...
- CSAPP Chapter 8:Exception Control Flow
prcesssor在运行时,假设program counter的值为a0, a1, ... , an-1,每个ak表示相对应的instruction的地址.从ak到ak+1的变化被称为control ...
- vue中递归组件的使用
2019独角兽企业重金招聘Python工程师标准>>> 递归 简单来讲就是程序自己调用自身. vue中的递归组件就是,组件自身调用自身. 父组件 <template> & ...
- LinearLayout控件
LinearLayout是线性布局控件,它包含的子控件将以横向或竖向的方式排列,按照相对位置来排列所有的widgets或者其他的containers,超过边界时,某些控件将缺失或消失.因此一个垂直列表 ...
- opencv-11-中值滤波及自适应中值滤波
开始之前 在上一篇我们实现了读取噪声图像, 然后 进行三种形式的均值滤波得到结果, 由于我们自己写的均值滤波未作边缘处理, 所以效果有一定的下降, 但是总体来说, 我们得到的结果能够说明我们的算法执行 ...
- 图论--拓扑排序--HDU-1285确定比赛名次
Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委 ...
- HDU2937 YAPTCHA(威尔逊定理)
YAPTCHA Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Subm ...
- 在linux上搭建nacos集群(步骤详细,linux小白也搞得定)
(1)nacos官网:https://github.com/alibaba/nacos/releases/tag/1.2.1下载nacos安装包到window本地(后缀为tar.zip) (2)在li ...
- 解决虚拟机中linux系统无法使用本机无线wifi联网的问题
VMware Workstation 在嵌入式开发中经常会遇到,但是显示大多数人使用开发环境是Win10 + 无线网卡,针对这种情况,需要配置虚拟机的上网环境使用的是NAT模式,将配置过程进行描述: ...
- 详解十大经典数据挖掘算法之——Apriori
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是机器学习专题的第19篇文章,我们来看经典的Apriori算法. Apriori算法号称是十大数据挖掘算法之一,在大数据时代威风无两,哪 ...