免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: zagorot
打印 上一主题 下一主题

[性能] php写的B/S应用系统中如何限制系统用户数? [复制链接]

论坛徽章:
0
61 [报告]
发表于 2005-12-01 13:18 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
62 [报告]
发表于 2005-12-01 13:23 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
63 [报告]
发表于 2005-12-01 14:28 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽

论坛徽章:
0
64 [报告]
发表于 2005-12-01 15:36 |只看该作者
原帖由 北京野狼 于 2005-12-1 10:18 发表
看来您除了想象力惊人以为,至少理解力 和LZ一样,需要几十遍的重复。那我直接问清楚,

服务器是如何知道用户关闭浏览器,断网的?

后台删除session的程序是如何区分什么session是用户关闭浏览器的可以删除,
什么session是用户超时的不能删除


先前我说的不详细,可能大家没理解到,我详细说明一下思路。

首先,服务器肯定不可能知道用户是断网还是关闭浏览器什么。
但我根本不需要去判断这个。

假设 session 的失效时间是 30 分钟,那么服务器超过30分钟还没有收到浏览器发来的请求时,自然该 session 就作废了。session 作废以后,自然就算作用户已经被注销了。

OK,如果用户关闭了窗口,那么 session 是不是也要等 30 分钟才会失效呢?

答案是YES

====================================================================

“哦,那这就是大问题了!用户不小心关闭了窗口,必须等 30 分钟,session 失效以后才能再次登录。因为登录时会检查该用户是否已经登录过了。”

但实际情况呢?

实际情况是这样:当用户关闭浏览器窗口,然后再次打开一个新窗口访问服务器。服务器并不会使用先前的那个 session id 来标示这次回话,而是分配一个新的 session id。

如此就解决了用户关闭窗口后必须等 30 分钟才能登录的问题。

====================================================================

问题总是环环相扣,解决了登录问题,那很显然又会带来另一个问题:

假如系统上限是 30 个人,现在正好有 30 人在使用。突然其中一人不小心关闭了窗口,然后再次访问服务器,这个时候 session 数就变成了 31 (因为新开的窗口会分配新的 session id)。那这个用户很明显就会被拒绝登录。

虽然这个问题只有在访问人数接近或者达到上限时才会发生,但仍然可以稍加处理来缓解这个缺陷。

====================================================================

为了缓解这个缺陷,我在方案中引入了在线记录这个东西。

在线记录主要保存下面几项信息:用户的 user id,以及 session id 和 最后操作时间。

由于在线记录的失效时间很短,例如 1 分钟。只要用户超过一分钟没有进行操作,该记录就会被删除。


可这个在线记录拿来做什么用呢?
这个在线记录需要和 session,以及用户登录结合起来使用。

但为了结合使用,session 就不能采用 php 默认的保存机制,而是需要实现自定义的保存机制。

====================================================================

php 默认的 session 机制是按照 session id 来标示一个 session,现在我们在自定义的保存机制中,
附带保存一个 user id。

好了,现在我们有了 session、在线记录、用户信息数据库,我们的用户登录程序可以按照下面的方式工作:

1、检查用户名、密码、图形验证码
2、在 session 库(也就是我们自定义的保存 session 数据的数据库)中,搜索是否存在该 user id 的 session 数据。
    如果“有”,则进一步判断 在线记录中是否有该 user id 的数据
        如果“有”,说明用户已经登录了,并且在 1 分钟之内还在操作系统。
            那么这次登录就可能是用户尝试从第二个地点使用同样的账号登录系统。
            或者是用户关闭窗口后,在 1 分钟之内重新登录。但不管是哪一种情况,
            系统的处理都是 拒绝登录
        如果“无”,则有两种情况:
            1、用户登录后超过了 1 分钟没有进行操作,
               然后其他人在第二个地点使用同样的账号进行登录;
            2、用户关闭了窗口,并且过了 1 分钟后再次登录。
            那么应该如何处理这种情况呢?
            这可以采用两种方式:
                a、直接允许登录,然后删除先前的 session。直接效果就是
                   先登录的用户被后登录的挤下了系统。就像同一个QQ号在
                   不同地方登录的效果一样。
                b、可以结合其他手段进一步检测用户情况。例如用户登录成功
                   后就设置一个 cookie。此时就能判断该 cookie 是否存在。
                   如果存在,说明是用户发生意外后重新登录,如果不存在,
                   则有可能是多个地点用同一账号登录。检测过后再决定是否
                   拒绝登录。
    如果“无”,则简单统计一下现有 session 总数就能确定是否允许登录了。

3、允许登录后,还有许多工作要做,包括:
   a、保存 session 信息
   b、生成在线记录

这就是登录处理过程,复杂的地方主要就在“数据库中已经存在该 user id 的 session”时决定是否允许登录。

====================================================================

注销用户就比较简单了,直接删除 session 和 在线记录 即可。

====================================================================

那么如何确保及时更新在线记录和 session 记录呢?

对于 session 记录,只要在 php 中注册了自定义的 session 处理函数,php 会在适当的实际自动调用你注册的 session 清理函数。

而对于在线记录,就要复杂多了。最好是写到一个公用文件中,然后在每一个操作文件中都 include 这个文件。
(这里用单一入口就比较方便)

====================================================================

整个方案肯定有很多漏洞,而且还要辅助其他手段才能达到良好的效果,例如:

1、代码肯定要加密,否则一切都是白搭;
2、session 数据库如果可以,自己做成自定义格式的文本数据库(应付几十个在线用户根本不是问题),甚至是共享内存。就算不能做成自定义格式,也要将关键信息加密存储到 SQL 数据库中。
3、在线记录和 session 一样,能自定义格式就自定义格式,否则就加密存储。
4、关键部分的代码必须写在一个文件里面加密,如果分离成多个文件,一是被破解的几率大,二是有可能被人分析出其中的工作原理,另外写一个来代替你加密后的文件。

目前我想到的漏洞主要是在极端情况(也就是当前在线用户数接近或者达到上限时),登录判断可能会判断失误。
但这个我想不是太大的问题,简单的增加一点用户上限数就行了。

例如卖给用户的是 30 用户版,那我系统实际上可以容纳 33 人在线,就大大降低出问题的几率了。

====================================================================

最后,我想说的。光靠编程语言,脱离了运行环境,要实现这种在线用户数量限制是很麻烦、效果可能也不够完美。

但是选择什么方案来解决问题,不能只考虑技术,还要考虑环境因素。现在 LZ 的软件明显是在一个不受控环境中执行,那在这种环境下争论是不是能够单纯用编程语言解决在线人数上限问题,根本没意义。

重要是找到一个可以接受的解决方案来达到目的!

论坛徽章:
0
65 [报告]
发表于 2005-12-01 15:37 |只看该作者
原帖由 wangyih 于 2005-12-1 13:23 发表



dualface的方法实践起来有相当的不足。
几乎不可实现,最好另选方案。



是的,我先前的方案很不完善,我重新写了一下。

虽然大体没变,但细节上考虑多了些。



不过我觉得如果你能够具体指出哪些地方不足就更好了。

论坛徽章:
62
2016科比退役纪念章
日期:2016-06-28 17:45:06奥兰多魔术
日期:2015-05-04 22:47:40菠菜神灯
日期:2015-05-04 22:35:07菠菜神灯
日期:2015-05-04 22:35:02NBA季后赛大富翁
日期:2015-05-04 22:33:34NBA常规赛纪念章
日期:2015-05-04 22:32:032015年亚洲杯纪念徽章
日期:2015-04-14 16:54:452015年亚洲杯之朝鲜
日期:2015-03-19 23:03:16明尼苏达森林狼
日期:2015-03-16 21:51:152015小元宵徽章
日期:2015-03-06 15:57:202015年迎新春徽章
日期:2015-03-04 09:55:282015年辞旧岁徽章
日期:2015-03-03 16:54:15
66 [报告]
发表于 2005-12-01 16:04 |只看该作者
原帖由 dualface 于 2005-12-1 15:36 发表


先前我说的不详细,可能大家没理解到,我详细说明一下思路。

首先,服务器肯定不可能知道用户是断网还是关闭浏览器什么。
但我根本不需要去判断这个。

假设 session 的失效时间是 30 分 ...



您的钻研精神确实很令人钦佩,比无聊的人强得多。

老实说,没时间全看完你的新方案。和早上那个方案是根本性的改变,

这次有些可行性。但是实现起来估计比LZ的系统本身都麻烦。

其实一直都没有真正有效的控制在线用户的方案,尤其LZ自己不能控制环境,

根本就没法实现。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
67 [报告]
发表于 2005-12-01 16:05 |只看该作者
dualface说得和我想的差不多,就是在session上做文章,关键是精确的寻找到哪些session记录是有效的,并且及时的清除无效的session记录
session的清理是根据session.gc_divisor设置调用session清理函数的几率,所以这个值应该设置得尽量小,甚至可以考虑设置为1
session的生存时间也要设置的短点,否则容易被僵尸把位置长期霸占
session记录可以考虑放到sqlite或者bdb这种文件型数据库内

>例如卖给用户的是 30 用户版,那我系统实际上可以容纳 33 人在线,就大大降低出问题的几率了
如dualface所说的,实际可以使用的用户数应该稍微高一点,因为session这东西终归感觉无法精确的控制,稍微调高一点点,出问题的几率会低一些

纸上谈兵终归是纸上谈兵,楼主如果觉得这个方向可行的话,不妨自己写来看看,反正也不复杂

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
68 [报告]
发表于 2005-12-01 16:19 |只看该作者
原帖由 北京野狼 于 2005-12-1 16:04 发表



您的钻研精神确实很令人钦佩,比无聊的人强得多。

老实说,没时间全看完你的新方案。和早上那个方案是根本性的改变,

这次有些可行性。但是实现起来估计比LZ的系统本身都麻烦。

其实一直都没有真正 ...


我觉得不复杂啊,其实就是做两个东西
一个是自定义session的存储,就是session_set_save_handler(),这个东西稍微有点php开发经验的人都可以写
第二个是检查有效的session个数,按照session生存时间排一下序,找出超标的那几个session id,如果当前的用户的session id正好在其中的话,输出错误信息,我想这个也不会太难,这个功能可以封装成一个函数

至于在程序的什么地方调用这个函数,要看程序的具体结构而言了,和这个函数本身没有太大关系

当然要做到精确的控制在线用户恐怕是有点难的,所以刚才也在建议把实际的用户数稍微设高一点
总之,希望可以达到80%的效果就不错了,毕竟http是无状态协议,从根基上就有问题。

从使用者的角度来说,假定进入系统进行某些操作,需要5分钟的时间,但是只要我们能够把误差时间控制在5分钟之内,目的就达到了,就算没有100%的精确也无所谓。
这个要看楼主的系统具体是什么功能了,从控制使用人数的角度来推算,很可能是OA一类需要长时间使用的系统。

[ 本帖最后由 夜猫子 于 2005-12-1 16:20 编辑 ]

论坛徽章:
0
69 [报告]
发表于 2005-12-01 16:34 |只看该作者
哈哈,这么老的帖子今天又看到了。

论坛徽章:
0
70 [报告]
发表于 2005-12-01 16:42 |只看该作者
啊,大家给了这么多建议啊. 非常感谢!

确实,我的软件在安装在客户的公司以后,将处于不受控制的环境下,一切状态均未知.

我把手头的一点事情忙完,会尽快尝试大家的建议方案.
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP