大部分分布式通信系统中,都会涉及到客户端之间相互通信、以及需要将客户端进行分组的功能,或者是类似这方面的需求。ESFramework对这一常见的任务内置了强大的支持,包括从客户端到服务端、一直到Platform的群集。在设计时,我们就考虑到了如何对常见的好友通信与组广播通信进行最大的支持,以期让ESFramework的使用者非常容易的就能够使用这些功能。

在ESFramework中,好友与组的成员并不仅仅是指用户(某人),而是指所有运行的客户端实例。只要两个客户端实例之间需要频繁相互通信,那么它们就可以建立好友关系(friend)。如果需要在某些特定的客户端实例间进行广播通信,那么这些实例就可以被划分到同一个组,成为组友(groupmate)。如果是使用ESFramework开发IM系统,那么这两种关系就更明显,它们就类似QQ的好友与群。

一.非强制性依赖

ESFramework提供了好友管理和组管理的接口(IFriendsManager与IGroupManager),如果你的应用需要好友与组方面的功能,那么只要实现这两个接口,并注入到ESFramework框架中,就可以拥有ESFramework内置的好友与组方面的强大功能了。但是,如果你的应用中仅仅是客户端与服务器进行通信,不需要好友与组方面的功能,那么,你就可以直接使用框架内置的null object模式的EmptyFriendsManager和EmptyGroupManager作为占位符对象。

ESFramework 并不会强制性地要求你的应用必须要实现一个与自己的项目需求没有任何关系的接口(比如IFriendsManager与IGroupManager)。我们将选择的权利交到了你的手中,你可以根据项目的具体需求,决定要实现哪些接口,并注入到ESFramework框架中。甚至,你可以只实现IFriendsManager和使用EmptyGroupManager;或者反过来,只实现IGroupManager和使用EmptyFriendsManager。要如何做,完全取决于你的项目要求。

二.好友管理

ESFramework 内置了最简单的好友管理接口ESPlus.Core.Server.IFriendsManager,其定义如下:


    public interface IFriendsManager
    {       
        /// <summary>
        /// 获取好友列表。
        /// </summary>     
        List<string> GetFriendList(string ownerID);
    }

该方法用于获取某个用户的所有好友的UserID列表。同很多常见的返回集合的方法设计规则一样,该方法不允许返回null,如果目标用户没有任何好友,那么请返回元素个数为0的List。接下来我们看,有了IFriendsManager这个接口,框架可以提供哪些与好友相关的功能或特性。

(1)用户上/下线时,通知其好友。当用户上线或下线时,框架会回调ESPlus.Application.Basic.Passive.IBasicBusinessHandler接口的OnFriendConnected方法或OnFriendOffline方法以通知所有的在线好友。

(2)客户端可以通过ESPlus.Application.Basic.Passive.IBasicOutter接口的GetFriends方法和GetAllOnlineFriends方法来获取所有好友以及所有在线的好友列表。

有了这两组特性的支持,每个运行的客户端实例,在其运行的整个生命周期中,都可以清楚地知道每个好友的在线状态。在具体项目中,我们可以这么做,当某个客户端登陆成功后,就获取所有好友列表和所有的在线好友列表,然后在运行的过程中,当接收到IBasicBusinessHandler的回调通知时,就修改对应好友的状态。这样就保证我们的客户端可以实时地知道每个好友是否在线。

ESFramework 内置了IFriendsManager接口的两个实现,一个就是上面提到的占位符EmptyFriendsManager,还有一个是DefaultFriendsManager。

(1)EmptyFriendsManager 假设所有的用户都不是好友关系 -- 即其GetFriendList方法始终返回一个元素个数为0的列表。

(2)DefaultFriendsManager 则假设所有的在线用户都是好友 -- 即其GetFriendList方法始终返回所有在线用户列表(将自己ownerID排除在外)。

三.组管理

组管理比好友管理稍微复杂一些,其复杂是因为一个用户可以加入到多个组,而且不同的组的成员是可以重复的。ESFramework 内置了最简单的组管理接口ESPlus.Core.Server.IGroupManager,其定义如下:


    public interface IGroupManager
    {
        /// <summary>
        /// 获取某个组的所有成员列表。
        /// </summary>      
        /// <param name="groupID">目标组ID</param>
        /// <returns>组成员的UserID列表</returns>
        List<string> GetMemberList(string groupID);         /// <summary>
        /// 获取目标用户的组友列表(即目标用户所属的所有组的成员的并集)。
        /// </summary>
        /// <param name="userID">目标用户ID</param>
        /// <returns>组友的UserID的列表。注意,该列表不应包含目标用户自己。</returns>
        List<string> GetGroupmateList(string userID);         /// <summary>
        /// 获取目标用户加入的所有组的ID集合。
        /// </summary>
        /// <param name="userID">目标用户的UserID</param>
        /// <returns>包含了userID用户的所有组的ID列表</returns>
        List<string> GetOwnerGroupIDList(string userID);
    }

(1)这三个方法都返回一个列表,所以也遵循相同的方法设计规则:如果没有任何满足条件的结果,请返回元素个数为0的List。

(2)GetMemberList 用于获取一个组的所有成员列表。比如,在实现该接口时,我们可以从DB中加载目标组及组成员,然后返回成员列表。

(3)组友groupmate,即同属一个组的成员之间的相互关系。由于一个用户可以加入到多个组,所有其组友就是所有这些组的成员的并集。注意,GetGroupmateList方法返回的列表中不能包含重复的UserID。

(4)一个用户可以属于多个组,GetOwnerGroupIDList方法用于获取某个用户加入的所有组的GroupID的列表。

接下来我们看,有了IGroupManager这个接口,框架可以提供哪些与组相关的功能或特性。

(1)用户上/下线时,通知其所有组友。当用户上线或下线时,框架会回调ESPlus.Application.Basic.Passive.IBasicBusinessHandler 接口的OnGroupmateConnected方法或OnGroupmateOffline方法以通知所有的在线组友。

(2)客户端可以通过ESPlus.Application.Basic.Passive.IBasicOutter接口的GetAllOnlineGroupmates方法来获取所有在线的组友列表。

(3)当我们发送组广播消息时(比如ESPlus.Application.CustomizeInfo.Passive.ICustomizeInfoOutter 接口的BroadcastInGroup方法),框架通过IGroupManager接口的GetMemberList方法才知道要将消息广播给哪些用户。

同IFriendsManager一样,有了(1)和(2)特性的支持,每个运行的客户端实例,在其运行的整个生命周期中,就可以清楚地知道每个组友的在线状态了。

ESFramework 内置了IGroupManager接口的一个实现,就是前面提到的占位符EmptyGroupManager,它对接口的三个方法的实现都是返回元素个数为0的列表。

 四.与ESPlatform的集成

ESPlatform的主要目的是通过应用服务器的群集以支持巨大并发。当将一个基于ESFramework的通信系统迁移到ESPlatform时,与好友和组相关的功能特性仍然可以正常使用。服务端和客户端程序几乎不需要修改,只需要将服务端原先配置的本地的IFriendsManager引用和IGroupManager引用修改为ESPlatform中平台层的对应的全局的Remoting引用即可,可以参见ESFramework 4.0 进阶(09)-- ESPlatform 支持的三种群集模型 一文简单了解平台层以及全局的FriendServer和GroupSever。

 五.请注意性能

如果具体的项目中需要频繁地用到好友与组等特性,那么在实现IFriendsManager接口和IGroupManager接口时,要特别注意性能问题。因为IFriendsManager接口和IGroupManager接口的方法会被框架频繁调用,所以,必须想办法提高IFriendsManager和IGroupManager接口的实现的性能。

如果IFriendsManager和IGroupManager接口的方法被调用时,每次都需要从外部介质(比如DB、文件等)重新加载好友关系与组关系,那么毫无疑问将严重地降低应用程序的性能。通常的解决方案是,使用缓存避免重复读取。当好友关系与组关系没有发生变化时,直接从内存返回对应的列表。

至于究竟采用何种策略来提升IFriendsManager和IGroupManager的性能,需要根据你的项目具体情况而作妥当设计。特别是在高性能的分布式通信系统中,这一点是万万不可忽视的。

好友与组--ESFramework 4.0 进阶(11)的更多相关文章

  1. 垂直分割群集模型与多通道引擎 -- ESFramework 4.0 进阶(10)

    在ESFramework 4.0 进阶(09)-- ESPlatform 支持的三种群集模型一文中,我们介绍了ESPlatform支持的三种群集模型 -- 垂直分割模型.水平分割模型.交叉模型.我们看 ...

  2. 消息同步调用-- ESFramework 4.0 进阶(07)

    分布式系统的构建一般有两种模式,一是基于消息(如Tcp,http等),一是基于方法调用(如RPC.WebService.Remoting).深入想一想,它们其实是一回事.如果你了解过.NET的Prox ...

  3. 挂接P2P通道-- ESFramework 4.0 进阶(08)

    最新版本的ESFramework/ESPlus提供了基于TCP和UDP的P2P通道,而无论我们是使用基于TCP的P2P通道,还是使用基于UDP的P2P通道,ESPlus保证所有的P2P通信都是可靠的. ...

  4. 在线用户管理--ESFramework 4.0 进阶(05)

    无论我们采用何种通信框架来构建我们的分布式系统,在服务端进行用户管理都是非常重要的一个环节.然而用户管理是否应该隶属于通信框架了?这个并不一定,通常来说,用户管理是与具体应用紧密相关的,应该是由应用解 ...

  5. 正规消息发送器-- ESFramework 4.0 进阶(06)

    在ESFramework 4.0 进阶(04)-- 驱动力:通信引擎(下)一文末尾我们已经将通信引擎以及整个消息骨架流程组装起来了,只要通信引擎一接收到消息,框架就会按照规定的流程进行运转.到这里,自 ...

  6. ESFramework 4.0 进阶(04)-- 驱动力:通信引擎(下)

    在ESFramework 4.0 进阶(03)-- 驱动力:通信引擎(上)一文中,我们对ESFramework提供的每一个通信引擎的接口都做了详细了说明,这篇文章我们将继续探讨这些接口的实现类 -- ...

  7. 驱动力—— 通信引擎(上)—— ESFramework 4.0 进阶(03)

    在ESFramework 4.0 进阶(02)-- 核心:消息处理的骨架流程一文中我们详细介绍了ESFramework中消息处理的骨架流程,并且我们已经知道,ESFramework中的所有通信引擎使用 ...

  8. 核心梳理——消息处理的骨架流程——ESFramework 4.0 进阶(02)

    在ESFramework 4.0 概述一文中,我们提到ESFramework.dll作为通信框架的核心,定义了消息处理的骨架流程,本文我们来详细剖析这个流程以及该骨架中所涉及的各个组件.ESFrame ...

  9. ESFramework 4.0 进阶(01)-- 消息

    需要交互的分布式系统之间通过消息来传递有意义的信息.消息是通信框架的核心.离开了消息,再谈通信框架就没有任何意义,所以,消息是ESFramework中一个最核心的概念. 一. 消息的类别 在具体的应用 ...

随机推荐

  1. git submodule相关操作

    $ cd 项目目录 // 初始化 $ git init $ git submodule add https://github.com/XXXX // 普通更新 $ git submodule upda ...

  2. 终于了解了User-Agent的历史了

    你是否好奇标识浏览器身份的User-Agent,为什么每个浏览器都有Mozilla字样? 1 Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.3 ...

  3. 设计模式 -- 组合模式 (Composite Pattern)

    定义: 对象组合成部分整体结构,单个对象和组合对象具有一致性. 看了下大概结构就是集团总公司和子公司那种层级结构. 角色介绍: Component :抽象根节点:其实相当去总公司,抽象子类共有的方法: ...

  4. 【Android-UI】包含多个子View时触发父节点的焦点事件

    今天遇到个问题: 在 LinearLayout 中添加了好几个其他视图 View 之后,点击时不能获得焦点,导致绑定的 onClick 事件不能触发. 解决办法: 对 LinearLayout 添加属 ...

  5. object model 概述

    Object Model 综述 标准 C++ 的对象模型为对象的动态特性提供了运行时的支持. 但是它静态的本性决定了在某些领域它表现出僵化.不可扩展的特点. GUI编程就是一个既需要运行时编译的效率, ...

  6. [APP]如果你想反编译

    反编译,主要用到两类工具,一个就是获取apk包的包名(appPackage)和类名(appActivity)的工具,其实就是反编译出java源代码,dex2jar和jd-gui:一个是将一个apk包反 ...

  7. redis cluster中添加删除重分配节点例子

    redis cluster配置好,并运行一段时间后,我们想添加节点,或者删除节点,该怎么办呢. 一,redis cluster命令行     //集群(cluster)  CLUSTER INFO 打 ...

  8. linux 调整文件系统大小 LVM

    fuser -m /home umount /home lvreduce -L 150G /dev/mapper/centos-home lvextend -L +300G /dev/mapper/c ...

  9. 搭建属于你自己的RAMOS系统 – WIN7+VHD+GURB map方式

    前段时间加了一个内存条,将笔记本内存升级到了6G,由于之前用的是32位的win7不可以直接使用6G内存,便装了64位的系统.网上找资源的时候发现,大内存可以使用RamOS,从内存中虚拟出来一个硬盘,然 ...

  10. mis 系统的开发具备的条件

    MIS的开发方式有自行开发.委托开发.联合开发.购买现成软件包进行二次开发几种形式.一般来说根据企业的技术力量.资源及外部环境而定. 补充: 管理信息系统的开发策略不可行的开发方法:组织结构法,机械的 ...