在制定一个规模比较多大的聊天应用时,往往需要制定部署多个应用服务,其一可以保障服务的可靠性,其二可以增加用户负载量.但制定这样一种应用体系是一件复杂的事情,毕竟同一群体的用户实际上会在不同的服务器接入,这样信息转发和处理就是一件比较麻烦的事情.但通过smartroute的订阅机制这一系列的事情都变得简单.

依据客观情况在设计的时候一般都只是功能优先,对于大规模的应用往往是后期扩展.但是基于集群扩展在设计上就需要做得很多工作作和规划.然而使用smartroute则会变得非常简单,因为并不需要在设计和规划上做多余的工作即可实现跨服务器集群交互.也许你感觉这是不太可能的事情,但以下示例会让你感觉到smartroute的智能之处.

  

对于以上场景设计需要考虑的事情比较多除了考虑节点和节点的通讯外,还需要考虑用户所登陆的节点,消息如何路由转发和增加节点需要如何切入集群等复杂技情况.而用smartroute不需要安装任何服务和配置即可自动完成,接下来看下如果使用smartroute来解决一些看去都很复杂的工作.

集群服务端实现

如是一开始上面架构规划设计,那肯定是很复杂的工作,那加入smartroute后的设计到底怎样呢?

        private static IServer mServer;

        static void Main(string[] args)
{ Route.AddLogHandler(new ConsoleLogHandler(LogType.DEBUG | LogType.ERROR | LogType.FATAL | LogType.INFO | LogType.NONE | LogType.WARN));
Route.DefaultNode.Open();
mServer = ServerFactory.CreateTCP();
mServer.Handler = new Program();
mServer.Port = 8012;
mServer.Open();
System.Threading.Thread.Sleep(-1);
} public void Connect(Beetle.Express.IServer server, Beetle.Express.ChannelConnectEventArgs e)
{
TCPSubscribeHandler tcpsub = new TCPSubscribeHandler();
tcpsub.Channel = e.Channel;
SmartRoute.Protocol.Packet packet = new SmartRoute.Protocol.Packet();
packet.Channel = e.Channel;
packet.Receive = OnMessageReceive;
e.Channel.Package = packet;
Route.Subscribe(e.Channel.ID, tcpsub);
} public void Disposed(Beetle.Express.IServer server, Beetle.Express.ChannelEventArgs e)
{
Route.UnSubscribe(e.Channel.ID);
UnRegister ureg = new UnRegister();
ureg.IP = e.Channel.EndPoint.ToString();
ureg.Name = e.Channel.Name;
ureg.SendTo(s => s.Mode(ReceiveMode.NotEq), e.Channel.ID);
} private void OnMessageReceive(object sender, Beetle.Express.PackageReceiveArgs e)
{
IMessage message = (IMessage)e.Message;
switch (message.MessageType)
{
case "Register":
Register reg = message.GetBody<Register>();
e.Channel.Name = reg.Name;
reg.IP = e.Channel.EndPoint.ToString();
reg.SendTo(s => s.Mode(ReceiveMode.All), e.Channel.ID);
break;
case "Speak":
Speak speak = message.GetBody<Speak>();
speak.User = new Register();
speak.User.Name = e.Channel.Name;
speak.User.IP = e.Channel.EndPoint.ToString();
speak.SendTo(s => s.Mode(ReceiveMode.NotEq), e.Channel.ID);
break;
}
}

你没有看错,以上代码就是一个基于集群的简单聊天服务网关,看上去是不是比编写一个普通网络程序的来得更简单多.接下来讲解一下主要代码的作用.

注册订阅

当网关接受到接入的时候会向节点注册一个订阅Route.Subscribe(e.Channel.ID, tcpsub);,而订阅的ID则连接在当前服务的唯一标识,而订阅实现是一个TCP连接订阅.

  取消订阅

当网关接受到断开的时候则取消订阅 Route.UnSubscribe(e.Channel.ID);

发送消息

而当网关接收到消息的情况则把消息投递出去,reg.SendTo(s => s.Mode(ReceiveMode.All), e.Channel.ID)是投递给所有订阅, speak.SendTo(s => s.Mode(ReceiveMode.NotEq), e.Channel.ID)则投递给非当前Channel.ID的所有订阅

智能组建节点集群

如果这个服在当前局域网内只运行一个实例,那它紧紧是一个普通的服务端,但如果节点发现网内还有其他节点在运行的情况下则会去发现对方并组建成通讯集群.当组建集群后每个节点的订阅信息都会同步到不同节点下,每个节点都是相互直连不存在中心服务.当一个节点接收一个消息投递的时候会找相应的订阅,如果是本机订阅则会直接调用订阅;如果是订阅在其他节点则把消息投递到相应的节点,由相应的节点调用订阅.

单节点动行效果

  

多节点运行效果

一旦节点发现网内有其它节点就会发现组建集群并同步订阅,一集群组建完成后就可以通过节点进行信息交互.

总结

实际上一个聊天服务的功能并不这么简单,往往具备有大厅,群组等等.其实使用smartrote处理这些信息转发则是非常简单的事情.可以针对大厅,群组制定订阅服务节点;然后消息发送到相关订阅,然后再由这些服务查找出具体的订阅用户然后分发即可.所以smartrote的订阅看上去是很简的功能,实现上可以实现很多意想不到的功能,如FTP,HTTP和MQ等等订阅的实现并注册到smartroute中统一集成分发.

下载完整示例代码

smartroute简单集成集群聊天通讯的更多相关文章

  1. SpringBoot学习笔记(13)----使用Spring Session+redis实现一个简单的集群

    session集群的解决方案: 1.扩展指定server 利用Servlet容器提供的插件功能,自定义HttpSession的创建和管理策略,并通过配置的方式替换掉默认的策略.缺点:耦合Tomcat/ ...

  2. .Net Core开源通讯组件 SmartRoute(服务即集群)

    SmartRoute是基于Dotnet Core设计的可运行在linux和windows下的服务通讯组件,其设计理念是去中心化和零配置即可实现服务通讯集群.SmartRoute是通过消息订阅的机制实现 ...

  3. 【Quartz】配置最简单的集群

    在许多情况,我们希望我们的定时任务是可靠的,不会因系统故障.机器宕机而导致某一笔定时任务不能按时运行.这种情况下,我们就需要为Quartz做个集群. 最简单的情况,有两台机器或两个应用,同时维护一批定 ...

  4. redis单机安装以及简单redis集群搭建

    安装环境: 两台虚拟机都是Centos 7.0 IP分别为:192.168.149.132  192.168.149.133 Redis采用的版本是redis-3.2.4 集群是采用两台虚拟机模拟8个 ...

  5. 简单Hadoop集群环境搭建

    最近大数据课程需要我们熟悉分布式环境,每组分配了四台服务器,正好熟悉一下hadoop相关的操作. 注:以下带有(master)字样为只需在master机器进行,(ALL)则表示需要在所有master和 ...

  6. Spring Cloud Hystrix理解与实践(一):搭建简单监控集群

    前言 在分布式架构中,所谓的断路器模式是指当某个服务发生故障之后,通过断路器的故障监控,向调用方返回一个错误响应,这样就不会使得线程因调用故障服务被长时间占用不释放,避免故障的继续蔓延.Spring ...

  7. 基于docker-compose部署 简单nsq 集群

    主要目的是搭建一个测试环境,同时使用了nodejs 客户端sdk nsq 简单了解 nsqd:一个负责接收.排队.转发消息到客户端的守护进程 nsqlookupd:管理拓扑信息并提供最终一致性的发现服 ...

  8. 用python实现一个简单的socket网络聊天通讯 (Linux --py2.7平台与windows--py3.6平台)

    windows   --> windows 写法均在py3.6 客户端写法 import socket client = socket.socket() client.connect(('192 ...

  9. [开源精品] C#.NET im 聊天通讯架构设计 -- FreeIM 支持集群、职责分明、高性能

    FreeIM 是什么? FreeIM 使用 websocket 协议实现简易.高性能(单机支持5万+连接).集群即时通讯组件,支持点对点通讯.群聊通讯.上线下线事件消息等众多实用性功能. ImCore ...

随机推荐

  1. bootstrap-标题

    1.重置了margin-top和margin-bottom的值,h1到h3重置后margin-top的值都是20px:h4到h6重置后的值都是10px: 2.所有标题的行高都是1.1(也就是font- ...

  2. 在Abp中集成Swagger UI功能

    在Abp中集成Swagger UI功能 1.安装Swashbuckle.Core包 通过NuGet将Swashbuckle.Core包安装到WebApi项目(或Web项目)中. 2.为WebApi方法 ...

  3. Http协议的常见参数

    Requests部分 Header 解释 示例 Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html Accept-Charset 浏览器可以接受的字 ...

  4. new 一个button 然后dispose,最后这个button是null吗???

    结果当然不是,button虽然释放了资源,但是它扔指向原来的那个地址,故不等于null 可以用button.isdispose==true判断

  5. ubuntu linux mysql 安装 基本操作 命令

    mysql --help #如果有信息证明系统已经安装了mysql mysql -V #查看版本号 netstat -tap|grep mysql #检查mysql是否在启动状态 卸载mysql: s ...

  6. jquery修改table某列的值

    开发的过程中,我们经常会遇到一些数和值之间的转换,比如本例:学部:1.小学,2.初中,3.高中;当然实现方法很多种,可以后台代码,也可以使用脚本... 修改前: 修改后: 代码: $("#t ...

  7. 动态加载js文件

    由于最近在弄echarts,关于地图类的效果,但是全国地图整体的js文件太大了,加载很耗费资源,所以要根据不同省份加载不同地区的js地图, 于是就想的比较简单, var script = docume ...

  8. Codeforces Round #347 (Div. 2) (练习)

    A: 题意:找到[a, b]的最大公约数: 思路:相同时为本身,不同时为1. 套路:碰到水题别想太多: 猜想:两个相邻数,必有一奇一偶,如果偶数有因子3或者其他,奇数可不可能有相同的呢? 枚举一些数后 ...

  9. js中创建数组的方法

    1.声明或创建一个不指定长度的数组(Array)的方式为: 如:var arrayObj = new Array(); 2.声明或创建一个数组并指定长度的数组(Array)的方式为: 如:var ar ...

  10. Java程序员从笨鸟到菜鸟之(一百零二)sql注入攻击详解(三)sql注入解决办法

    sql注入攻击详解(二)sql注入过程详解 sql注入攻击详解(一)sql注入原理详解 我们了解了sql注入原理和sql注入过程,今天我们就来了解一下sql注入的解决办法.怎么来解决和防范sql注入, ...