Cowboy将为每个请求生成进程(在这种情况下,它是websocket连接,事件源请求或通过ajax进行长轮询)。
在用户之间发送消息只需通过向表示与该用户的连接的相应进程发送消息即可解决(如果您有两个用户且两者都支持websockets,那么是2个进程,每个进程代表websocket连接。
让我们说我有2个用户(Foo,Bar)。
Foo想要向Bar发送消息,所以Foo进程必须以某种方式获取与表示与用户栏的连接的牛仔进程相关联的pid (所以他可以发送定期向他发送erlang消息 - 消息在内部发送给用户webbrowser。
但是当Foo获得pid并且pid将变为无效时发生了什么,因为用户Bar将在此期间重新连接(重新连接意味着与Bar相关联的进程被终止并且因为Bar再次连接,他获得了新的过程)吗
由于网络问题,Bar重新连接。
这意味着如果Foo会向Bar发送消息(Foo已经过了pid,已经终止了),该消息将永远不会被传递。
第一个解决方案是,因为该消息可能是持久性的(例如Facebook上的消息),在将其发送给用户之前,您将始终将其保存到DB。 当用户连接时,必须进行一些同步,因为即使他有99%的在线时间,也可能有按摩他没有。因此,当重新连接后同步时,Bar将从Foo获取消息(消息将从数据库中提取)。
现在真正的问题是:如果Foo将无效的PID过长,该怎么办,即使在Bar重新连接并执行同步后他还会发送一些消息? Bar的消息将存储在数据库中,但由于它是在Bar同步后存储的,因此不会传递。
答案 0 :(得分:1)
正如您所知 - 将PID作为用户标识符并不是一个好的解决方案,因为它本身就是短暂的。我认为更好的解决方案是让用户Foo持有一些持久的用户ID ,无论用户是否已连接,都会识别用户栏。
您可以使用ETS或DETS(支持持久性)保持从用户ID到PID的映射,并向当前注册到永久用户ID的PID发送消息。
答案 1 :(得分:0)
所以foo和bar应该相互监视。如果一个进程死亡,另一个进程将收到消息{'DOWN', Ref, process, Pid2, Reason}
。正如Uri所说,您可以将流程专门用于维护路由表。
答案 2 :(得分:0)
您可以使用gproc lib。它确实使用ETS来注册,监控,发送消息和其他进程。您可以使用属性,唯一名称甚至计数器注册该过程,并使用ETS查询的强大功能查询它们。 API非常完整。
我认为如果你想要一些交付保证,你需要自己做。