我现在用的方法是这样的:
用户表中有一个IsOnline和ActiveTime字段,用户登录后IsOnline属性就为true,然后客户端每隔3秒给服务器端发送一个心跳包,刷新ActiveTime字段为当前时间,服务器每隔30秒扫描一遍IsOnline属性为true的用户,发现最后收到的心跳包时间与当前时间之差大于10秒的(保守假设在通信线路上消耗的时间为2秒,那么正常情况下服务器是每5秒收到一个心跳包,10秒即连续收不到两个心跳包),那么,便将该用户的IsOnline属性置为false,表明该用户断线了。这样的问题是:
假如有3W个在线用户,那平均每秒就有1W个包发到服务端,而且会执行1W条update语句,这个开销太疯狂了,而且还会随着用户的增加等比例上升。大家做这种应用的时候是采用什么方法的呢?分享一下PS:好奇QQ是采用什么样的方式才判断用户在线状态的。。
用户表中有一个IsOnline和ActiveTime字段,用户登录后IsOnline属性就为true,然后客户端每隔3秒给服务器端发送一个心跳包,刷新ActiveTime字段为当前时间,服务器每隔30秒扫描一遍IsOnline属性为true的用户,发现最后收到的心跳包时间与当前时间之差大于10秒的(保守假设在通信线路上消耗的时间为2秒,那么正常情况下服务器是每5秒收到一个心跳包,10秒即连续收不到两个心跳包),那么,便将该用户的IsOnline属性置为false,表明该用户断线了。这样的问题是:
假如有3W个在线用户,那平均每秒就有1W个包发到服务端,而且会执行1W条update语句,这个开销太疯狂了,而且还会随着用户的增加等比例上升。大家做这种应用的时候是采用什么方法的呢?分享一下PS:好奇QQ是采用什么样的方式才判断用户在线状态的。。
解决方案 »
- 高手请进: VS2010 怎么用水晶报表呢?
- datagridview 编辑 单元格后怎样保存?
- C#有没有类似于powershell的whatif的功能?
- 类、结构或接口成员声明中的标记无效
- 一个很棘手的问题 访问局域网内的SQL服务器问题
- c#2008评估期已过,怎么办?
- 新手提问,不要见笑:新建一个用户控件,产生的源码内的[]是干什么用的?
- C#页面中不传参数出现错误,如何处理?
- 一个选座系统,如何做这种图呢,或者有第三方空间也可以,系统是c/s的。
- 请教好心人,如何在winform64位下如何完美解决03,wps,07的EXCEL导入和导出。
- 自己编写的FTP客户端 服务器,连接出现问题
- gridview无法拖动
而不是client直接访问数据库,
心跳包更新的是应用程序服务的在线用户信息,而不是数据库,
如果用户太多,那么就不断地分割服务C/S中的S不是特指数据库服务器
心跳包自己定义,一般包括用户的信息。比如说用户的ID(唯一标示用户的)
然后在服务器中启动另外的线程接收客户端发过来的包。在统计数量。同时服务器也开始自己统计时间。
判断当多少时间内没收到包。判断用户离线。
具体技术:TCP编程。多线程编程。
1. 为什么要每隔3秒呢?为什么不是每隔15秒?2. 你的设计怎么跟数据库update扯上关系了呢?
实现心跳包一个比较好的方法是在服务器当接收到包后跟新一次数据库说明用户在线,然后通过程序中维护一张自定义表来判断用户离线。当离线判定成功在写一次数据库说明用户离线。
具体实现可以全部在服务器。
客户端首先发一个心跳包给服务器。
服务器接收到包过后,在Update到数据库一次。说明用户在线。(比如置状态为0)
然后服务器启动线程。每3S接收一次心跳包。统计每个用户心跳包个数。同时服务器在接收到客户端发送来的包时候自己也开始没3S计数。比较用户离线就判断服务器计数和客户端计数的相差多少就行了。
这样就可以不用每一次去写数据库
你误会了,我并没有让客户端直接连数据库,而是通过udp发包给服务器,服务器收到udp包后再更新数据库。我现在考虑的就是如果在内存中维护一个在线用户集合的话,然后我每隔30秒遍历一次这个集合,查看哪些用户已超过10秒没有心跳包发过来了,将他剔除这个集合。
这样的话,比如这个集合有3W条记录,每30秒遍历一次,感觉就很吃性能。
而且并发性也存在问题,比如在foreach遍历的时候,有另外的线程登录进来,就要将新用户加进集合中,这样遍历操作又会抛异常