基于mina的cs通信,含内存cache,mongodb持久化案例【第一篇】

分享的好处在于帮助别人的同时也能帮助自己,更多的人参与分析和使用会提升代码的质量。

先简单描述一下需求和设计思路吧。

1、需求:设计出来一套NIO的CS,client提供发送某种格式的数据;server提供接受数据并缓存同时提供持久化,用于提供实时查询和离线查询分析。

2、NIO选择:我在看了关于NIO框架的讨论分析后,决定选择mina,这个完全是自己的个人爱好。当然其他NIO如neety或者基于mina的openfire,也是不错的选择。

3、缓存:目前缓存有很多成熟的框架可以用,考虑我们的需求和服务器问题决定自己设计一套简单的缓存。server在接受多个client消息的时候,缓存数据过程势必会遇到同步问题,于是采用了ReadWriteLock、synchronized以及volatile等安全策略设计缓存,当然你也可以使用concurrent包来设计同步策略。其中一个特殊问题就是缓存数据的更新问题,每天有很多数据进入缓存,那么怎么清空过期的数据保证缓存不会爆掉?同时,client的设计呢?对于一个应用来说是分配一个client还是多个client呢,每个client是长连接还是短连接?

4、数据持久化:采用mongodb作为持久化存储db,封装了mongodb的操作,为了减少最终的jar体积,并没有使用spring的mongodb模块。在计算时采用mongodb的mapreduce进行聚合计算,这并不是最优的,因为用过mapreduce的人就会发现通常count、group速度比它要快。

5、整体流程介绍:多个client并发访问server,server解码数据并缓存,同时启动对缓存的守护进程进行轮询维护或批量持久化,调用server的接口访问缓存数据或mongodb中的离线数据。

然后说说在开发之前分析流程,设计方案,梳理出可能会存在的问题,以及应对的方案或选择的策略。

1、mina提供了handler来处理消息,但是不适合我的需求,我需要建立连接后主动去发送消息,那就需要在建立连接之后获取连接句柄,mina中其实就是iosession。解决方法是在handler中把iosession缓存起来,这样就完事了吗?事实并不这么简单,一个需要连接server的app中假如维护一个client长连接,那么这个app中可能有多个地方调用了client发送消息,这个iosession需要同步。

2、缓存的守护线程定时维护方案怎么设计?其实我并不想多讨论缓存,因为很多人可能用的是第三方的缓存框架了,但是既然提到了就简单说说吧。我考虑这个问题时分析了Timer、Quartz、JcronTab 等,首先放弃了Timer,因为timer不能保证准时触发job,同时如果发生异常Timer将会推出后续任务都放弃了,这太不安全了;Quartz和JcronTab非常棒,遗憾的是他们和外部环境的上下文隔离,这就意味着你不能访问缓存对象,显然不适合我的场景。最终考虑使用线程完成调度,daemon thread通过计算每一次任务执行点到当前时间点的时间间隔来进行sleep,时间结束后(定时点到达)启动一个新的线程(我称为jod-thread)来执行cache的维护任务,特别提醒这个daemon thread不要访问任何状态可变的共享变量,这样daemon thread必然准时触发,而jod-thread会慢慢执行自己的任务,如果job耗时太久,不会影响daemon thread,这时如果上一个jod thread 没执行完,daemon thread 会新启动一个jod thread 处理新任务, 也就是说会出现多个job-thread在并发处理任务,所以你要考虑你的业务场景在这种情况下的资源共享问题了,比如是否对共享变量加锁来同步等等。

在经过多线程测试后,目前版本已算稳定。 期待过年的心情无法安静,先用maven生成出API,年后把项目拿出来讨论吧。




郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。