Foxtable(狐表)用户栏目专家坐堂 → 移动端+PC端的并发独占编辑思路有必要问一下。


  共有2642人关注过本帖树形打印复制链接

主题:移动端+PC端的并发独占编辑思路有必要问一下。

帅哥哟,离线,有人找我吗?
chen3728060
  1楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:二尾狐 帖子:388 积分:5098 威望:0 精华:0 注册:2013/11/2 0:01:00
移动端+PC端的并发独占编辑思路有必要问一下。  发帖心情 Post By:2017/3/7 18:20:00 [只看该作者]

网络下复杂编号的已经解决,这个很简单,因为以前在OpenQQ时就是客户端发消息请求服务器端发送一个最新的编号过去,先在既然httpRequest请求都直接是服务器收到,那服务器可以直接从编号的字典里,给出最新的编号

Public flbhs As New Dictionary(of String,Integer)


以前OpenQQ就是用上面这个字典存编号


Dim msg As String = e.Message

If msg.StartsWith(":f") AndAlso msg.EndsWith("f:") Then
    msg = msg.SubString(2, msg.Length - 4)
    If pdbhs.ContainsKey(msg) Then '

    msg = msg.SubString(2, msg.Length - 4)

    If pdbhs.ContainsKey(msg) Then '如果存在这个类别的编号

        pdbhs(msg) = pdbhs(msg) + 1 '将该类别最大编号加1

    Else

        pdbhs.Add(msg,1) '如果是这个列表的首次编号,则编号等于1

    End If
    e.ReturnValue = pdbhs(msg)

    e.ReturnValue = pdbhs(msg) '将编号返回给客户端

End If


用上面的代码获取编号,现在只需要稍微改造一下,就可以给新编号。


不过我想问的是,独占编辑的思路,尤其是防止客户掉线后防止死锁的问题。



Public tbrk As new Dictionary(of String,String)

tbrk是一个字典,用于登记每一行是谁在编辑。

我们约定接下来编码的时候:字典的键由表名和行的主键组合成,值则等于编辑者名。



在OpenQQ,用了一个字典来登记谁在编辑。客户端要编辑,就会问服务器端谁在编辑,没人就登记一下,我编辑。在移动端这个问题很容易解决,收到HttpRequest时,也通过这个字典判断是否有人在编辑这行,没有就跳转编辑htm,有就弄个TopTips提示拒绝客户即可,容易。


问题在于客户掉线的死锁。在openQQ下,有个30秒的心跳机制,超时死亡了,就会执行UserLogout事件,把客户踢出这个独占编辑字典

Dim Keys As New List(of String)

For Each Key As String In tbrk.Keys
   If tbrk(Key) = e.UserName Then
      Keys.Add(Key)
    End
If

   If tbrk(Key) = e.UserName Then

      Keys.Add(Key)

    End If

Next

For Each Key As String In Keys

    tbrk.Remove(Key)

Next



但是在移动端对于客户存活状态判断,在新帮助文档的→WeUi框架→让登陆变得更加安全,

设计思路

1、服务端新建一个临时表,包括三列,分别是:UserName,UserID和ActiveTime

2、服务端在验证用户身份后,在临时表中新增一行,生成一个16位的随机字符串存储在UserID列,用户名和当前时间则分别存储在UserName和ActiveTime列。

3、完成上述操作后,再将UserName和UserID保存在Cookie中,其中UserName存储在Cookie中的是加密后的字符串。

4、为方便理解,本节的示例代码直接使用username和userid作为Cookie名称,实际开发的时候,请采用没有任何指示性的名称,注意Cookie名是区分大小写的,这里用的是小写。

5、用户在登录成功,继续访问其他页面时,Cookie中会包括username和userid,服务端根据username和userid从临时表中查找对应的行,此时会有三种可能:

    • 如果找到,且ActiveTime和当前时间相比,相差不超过30分钟,允许访问,并将ActiveTime列更新为当前时间。
    • 如果找到,但ActiveTime和当前时间相比,相差已超过30分钟,拒绝访问,并删除此行,然后跳转到登录页面。
    • 如果没有找到,则拒绝访问,直接跳转到登录页面。

6、如果用户在其他位置登录成功,服务端根据加密后的UserName在临时表中查找对应的行,如果找到,说明是重复登录,删除此行,使得前一次的登录无效;然后重复2、3操作,在临时表和Cookie中存储加密后的UserName和随机生成的UserID,并在ActiveTime列记录当前时间。

7、显然临时表的记录会越来越多,我们可以定期清除ActiveTime列和当前时间相比超过30分钟的行,也可以在表在超过约定行数后执行一次清理动作,本示例选择的是前者,每30分钟清理一次


用的是每次收到HttpRequest时,判断是否有超时30分钟的人,有就把它踢出。既然判断他超时,就是认为他断线了,所以也就只能此时把用户踢出  独占编辑字典。

这样就出现一个问题。有个A领导,打开了某个出库单据准备审核,然后他的垃圾手机死机了,他烦了,于是去开会了。独占编辑字典里,已经登记了这个领导在编辑,没有超过30分钟,系统都不会认定他断线死亡。然后这30分钟内,领导B想审核这个单据,就会提示领导A一直在编辑,他就很纳闷,于是他去问A,A领导说“我没有在编辑,你看我手机都坏了,电脑我也没开啊”。B领导就继续纳闷,苦等了半个小时。这咋解决?

核心问题在于  openQQ的心跳机制可以让超时死亡控制在30秒,移动端的ActiveTime的超时死亡在30分钟,咋解决?

①把ActiveTime的时间缩短,但是带来问题就是有时候手机端录入速度确实慢,例如我去仓库一个个数产品数量盘点,然后填入数量,由于已经没有点提交按钮,不会有新的HttpRequest触发,盘点时间过长,导致我被踢出了独占编辑。其他人又用手机或者电脑打开了这个单据修改,我先保存,然后他后保存,覆盖了我的记录,我做的功夫全白费了

难道我放一个看不到的异步Ajax玩意,每30秒触发一下服务器?


---------------------------------------
群里有人推荐了我去看HttpClient,解决这个。但是我看HttpClient貌似不是用在手机端的,而是用来开发管理公众号后台客户端的工具。

求思路解答

 回到顶部
帅哥哟,离线,有人找我吗?
有点蓝
  2楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:超级版主 帖子:106132 积分:539771 威望:0 精华:9 注册:2015/6/24 9:21:00
  发帖心情 Post By:2017/3/7 20:42:00 [只看该作者]

使用js计时器,按指定的间隔向服务器发送信息表示在线:http://www.w3school.com.cn/js/js_timing.asp



 回到顶部
帅哥哟,离线,有人找我吗?
chen3728060
  3楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:二尾狐 帖子:388 积分:5098 威望:0 精华:0 注册:2013/11/2 0:01:00
回复:(有点蓝)使用js计时器,按指定的间隔向服务器...  发帖心情 Post By:2017/3/7 21:36:00 [只看该作者]

如果是要用js实现心跳,这个东西太重要,希望狐爸把它整合进去

 回到顶部
帅哥哟,离线,有人找我吗?
有点蓝
  4楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:超级版主 帖子:106132 积分:539771 威望:0 精华:9 注册:2015/6/24 9:21:00
  发帖心情 Post By:2017/3/7 22:39:00 [只看该作者]

这种东西可能不好整合,参考用法

HttpRequest事件代码:

'通用事件头,用于发送已经存在的常见文件
Dim fl As String = "c:\web\" & e.path
If filesys.FileExists(fl)
    Dim idx As Integer = fl.LastIndexOf(".")
    Dim ext As String  = fl.SubString(idx)
    Select Case ext
        Case ".jpg",".gif",".png",".bmp",".wmf",".js",".css" ,".html",".htm",".zip",".rar"  
            e.WriteFile(fl)
            Return '这里必须返回
    End Select
End If
Select Case e.Path
    Case "count.htm"
        Dim wb As New weui
        Dim sb As New StringBuilder
        sb.AppendLine("<script src='http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js'></script>")
        sb.AppendLine("<script>")
        sb.AppendLine("var c=0;")
        sb.AppendLine("var t;")
        sb.AppendLine("function timedCount(){")
        sb.AppendLine("document.getElementById('xm').value=c;")
        sb.AppendLine("c=c+1;")
        sb.AppendLine("sendAjaxText('1','active.htm','',false);")
        sb.AppendLine("t=setTimeout('timedCount()',2000);")
        sb.AppendLine("}")
        sb.AppendLine("$(document).ready(function () {")
        sb.AppendLine("timedCount();")
        sb.AppendLine("});")
        sb.AppendLine("</script>")
        wb.AppendHTML(sb.ToString,True)
        With wb.AddInputGroup("","ipg1","计时")
            .AddInput("xm","0","text").Readonly = True
        End With
        e.WriteString(wb.Build) '生成网页
    Case "active.htm"
        StatusBar.Message2 = val(StatusBar.Message2) + 1
End Select

 回到顶部
帅哥哟,离线,有人找我吗?
zhangjian222200
  5楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:七尾狐 帖子:1528 积分:10778 威望:0 精华:0 注册:2016/9/12 11:18:00
  发帖心情 Post By:2017/8/28 20:28:00 [只看该作者]

发错了
[此贴子已经被作者于2017/8/28 20:28:38编辑过]

 回到顶部
帅哥哟,离线,有人找我吗?
zhy400137
  6楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:五尾狐 帖子:1131 积分:8199 威望:0 精华:0 注册:2013/11/3 19:00:00
  发帖心情 Post By:2017/8/28 20:43:00 [只看该作者]

mark

 回到顶部