ESFramework 开发手册(05)--好友与组

      本文介绍ESFramework 开发手册(00) -- 概述一文中提到的ESPlus的两翼:好友关系与组关系。     

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

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

 

1.非强制性依赖

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

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

 

2.好友管理

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

    public interface IFriendManager        
    {       
        /// <summary>
        /// 获取好友列表。该方法不允许返回null,如果没有任何好友,请返回元素个数为0的List。
        /// </summary>     
        List<string> GetFriendList(string ownerID);

        /// <summary>
        /// 当某个Owner的好友列表发生变化时,触发此事件。参数为OwnerID。该事件被用于CachedFriendManager。
        /// </summary>
        event CbGeneric<string> FriendChanged;
    }

       GetFriendList方法用于获取某个用户的所有好友的UserID列表。同很多常见的返回集合的方法设计规则一样,该方法不允许返回null,如果目标用户没有任何好友,那么请返回元素个数为0List

      当某个用户的好友发生变化时(比如,增加或移除好友),则应该触发FriendChanged事件,以通知ESFramework框架。特别是在ESPlatform群集平台中,各种类型的应用服务器将会按情况缓存部分好友列表,当框架接收到FriendChanged通知时,可以删除或更新已过期的缓存。如果是简单的应用,而且也不需要使用ESPlatform,那么在实现IFriendManager接口时,可以忽略FriendChanged事件。

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

  • 用户上/下线时,通知其好友。当用户上线或下线时,框架会触发IBasicOutter接口的FriendConnectedFriendOffline事件以通知所有的在线好友。
  • 客户端可以通过IBasicOutter接口的GetFriends方法和GetAllOnlineFriends方法来获取所有好友以及所有在线的好友列表。

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

        ESFramework 内置了IFriendManager接口的两个实现,一个就是上面提到的占位符EmptyFriendManager,还有一个是DefaultFriendManager

  • EmptyFriendManager 假设所有的用户都不是好友关系 --即其GetFriendList方法始终返回一个元素个数为0的列表。当项目中不需要使用好友关系时,可以使用该占位符。
  • DefaultFriendManager 则假设所有的在线用户都是好友 --即其GetFriendList方法始终返回所有在线用户列表(将自己ownerID排除在外)。DefaultFriendManager一般用于demo或者测试程序中,使得demo或测试程序的实现更简单。

 

3.组管理

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

    public interface IGroupManager        
    {
        /// <summary>
        /// 获取某个组的所有成员列表。该方法不允许返回null,如果没有任何组成员,请返回元素个数为0的List。
        /// 主要用于实现ESPlus.Application.CustomizeInfo空间的组广播等功能。
        /// </summary>      
        /// <param name="groupID">目标组ID</param>
        /// <returns>组成员的UserID列表</returns>
        List<string> GetMemberList(string groupID);

        /// <summary>
        /// 获取目标用户的组友列表(即目标用户所属的所有组的成员的并集)。该方法不允许返回null,如果没有任何组友成员,请返回元素个数为0的List。
        /// 主要用于实现ESPlus.Application.Basic空间的组友上下线通知、获取在线组友列表等功能。
        /// 实现时,可以采用缓存机制,以提高性能。
        /// </summary>
        /// <param name="userID">目标用户ID</param>
        /// <returns>组友的UserID的列表。注意,该列表不应包含目标用户自己。</returns>
        List<string> GetGroupmateList(string userID);

        /// <summary>
        /// 获取目标用户加入的所有组的ID集合。该方法不允许返回null,如果目标用户没有加入任何组,请返回元素个数为0的List。
        /// 该方法被用于ESPlatform。如果不需要ESPlatform,实现时直接返回元素个数为0的List。
        /// </summary>
        /// <param name="userID">目标用户的UserID</param>
        /// <returns>包含了userID用户的所有组的ID列表</returns>
        List<string> GetOwnerGroupIDList(string userID);

        /// <summary>
        /// 当某个组的成员发生变化时,触发此事件。参数为GroupID。该事件被用于CachedGroupManager。
        /// </summary>
        event CbGeneric<string> GroupMembersChanged;
    }
  • 前三个方法都返回一个列表,所以也遵循相同的方法设计规则:如果没有任何满足条件的结果,请返回元素个数为0的List。
  • GetMemberList 用于获取一个组的所有成员列表。比如,在实现该接口时,我们可以从DB中加载目标组及组成员,然后返回成员列表。
  • 组友groupmate,即同属一个组的成员之间的相互关系。由于一个用户可以加入到多个组,该用户的所有组友就是所有这些组的成员的并集。注意,GetGroupmateList方法返回的列表中不能包含重复的UserID。
  • 一个用户可以属于多个组,GetOwnerGroupIDList方法用于获取某个用户加入的所有组的GroupID的列表。
  • 当某个组的成员发生变化时(比如,增加或移除组员),则应该触发GroupMembersChanged事件,以通知ESFramework框架。特别是在ESPlatform群集平台中,各种类型的应用服务器将会按情况缓存组成员列表,当框架接收到GroupMembersChanged通知时,可以删除或更新已过期的缓存。

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

  • 用户上/下线时,通知其所有组友。当用户上线或下线时,框架会回调IBasicOutter 接口的GroupmateConnected或GroupmateOffline事件以通知所有的在线组友。
  • 客户端可以通过IBasicOutter接口的GetAllOnlineGroupmates方法来获取所有在线的组友列表。
  • 当我们发送组广播消息时(比如ICustomizeOutter 接口的BroadcastInGroup方法),框架通过IGroupManager接口的GetMemberList方法才知道要将消息广播给哪些用户。

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

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

 

4.请注意性能

       如果具体的项目中需要频繁地用到好友与组等特性,那么在实现IFriendManager接口和IGroupManager接口时,要特别注意性能问题。

实现时使用缓存

      因为IFriendManager接口和IGroupManager接口的方法会被框架频繁调用,所以,必须想办法提高IFriendManager和IGroupManager接口的实现的性能。
      如果IFriendManager和IGroupManager接口的方法被调用时,每次都需要从外部介质(比如DB、文件等)重新加载好友关系与组关系,那么毫无疑问将严重地降低应用程序的性能。通常的解决方案是,使用缓存避免重复读取。当好友关系与组关系没有发生变化时,直接从内存返回对应的列表。(在ESPlatform群集平台中,三种类型的应用服务器AS、BS、TS都针对好友和组内置了延迟加载机制和缓存机制)。
      至于究竟采用何种策略来提升IFriendManager和IGroupManager的性能,需要根据你的项目具体情况而作妥当设计。特别是在高性能的分布式通信系统中,这一点是万万不可忽视的。

精简好友/组友列表

      IFriendManager和IGroupManager返回的好友列表和组友列表,请尽可能的精简,不要包含垃圾数据。特别是当服务端引擎的FriendNotifyEnabled和GroupNotifyEnabled属性(将在后面介绍)设置为true时,用户的状态变化会自动通知其所有好友和组友。如果用户状态改变频繁,而其好友和组友数量又很巨大时,这种开销是非常大的。必要时,可以考虑将FriendNotifyEnabled或GroupNotifyEnabled设置为false以关闭状态改变自动通知。

      下一篇文章,我们将介绍分别用于服务端和客户端的Rapid引擎,敬请关注,谢谢。

      阅读 更多ESFramework开发手册系列文章

-----------------------------------------------------------------------------------------------------------------------------------------------

下载免费版本的ESFramework 以及 demo源码

关于ESFramework的任何问题,欢迎联系我们:

电话:027-87638960

Q Q:372841921

邮件:esframework@oraycn.com

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值