驽马十驾 驽马十驾

驽马十驾,功在不舍

目录
用户在线时长统计思路
/  

用户在线时长统计思路

需求

统计用户进入直播间的时长。

大体思路,细节可以结合业务自行完善。

思路

  • 客户端,每隔X秒发送一次新增时长请求,后端接收到请求后增加时长。
  • 服务端,因为通信使用的是基于Netty的Websocket,所以可以通过Netty的定时器进行时长增加。

客户端

对于客户端方案而言,需要客户端每隔一段时间发送一次新增时长的事件。对于服务端而言不能傻傻的获取到这个时长就新增,因为客户端的请求可能是不可靠的:

  • 用户可能伪造请求,比如没来10s加一次,用户通过模拟这个请求,1s发10次。
  • 用户多端登录,本来是10s加一次,现在2端登录,10s后,难道给用户加20s。

如何处理上述问题?我是通过记录用户最后一次新增时长时间戳的事件来处理的,本次事件和上一次事件的时间间隔必须大于规定时长,后端才会新增时长,然后替换最后一次事件的时间戳。

针对上一个思路,需要考虑:

  • 新增时长需要保证原子性。
  • 分布式环境下,需要要到分布式锁。
  • 如果不用分布式锁,那么就要保证用户的请求都是落到一个服务节点上的。

服务端

因为直播间需要聊天,技术上采用的是基于Netty的Websocket,此时在客户端不加任何代码的情况下,可以实现。

  • Netty有ctx.channel().eventLoop().scheduleAtFixedRate() 这个定时任务
  • 用户进入直播间后,新建这个定时任务,注意保存下生成的future方便离开直播间时移除
  • 用户离开直播间,通过保存的future移除。

至于如何保存这个future,方法很多。

  • 每一个Channel都要自己的id,可以通过map来映射
  • 每一个Channel可以绑定Attribute,可以通过这个API完成

那么具体选哪一个了?

  • 自己实现的Map相对来说复杂点,但是因为Map的查找的复杂度是O(1),所以性能好
  • ChannelAttribute默认实现是DefaultAttributeMap,他的修改是CopyOnWrite,不会造成锁,但是CPU利用率高。查询是二分查找,理论复杂度是 O(logn)。不过每一个Channel绑定的Attribute很少时候,性能差距不大。

结合自己的情况做选择。

对于增加时长的多端登录问题,后端的方案也会遇到,处理思路同上:保留最后一次增加时间事件的时间戳、分布式锁保证新增和替换是原子性。

结语

多思考,多总结。

骐骥一跃,不能十步。驽马十驾,功在不舍。