我正在开发一个简单的RESTful api(在NodeJ上)。我明白,保持平静意味着水平缩放会更容易。不幸的是,我需要一些方法让客户几乎立即得到某些事件的通知。出于这个原因,我正在考虑做长轮询。我的问题是如何使用多个服务器。例如,这是一个简化的用例:
Both servers A and B are behind a common load balancer.
User Alice posts a message on Bob's wall (PUT request on server A).
If Bob is online, he should be notified instantly (long-polling on server B).
服务器A如何向Bob发送通知,或者服务器B知道应该通知Bob?
答案 0 :(得分:2)
首先,我不知道为什么你不会在客户端和服务器上使用类似socket.io
的东西来处理你的通知频道。这将使用Web套接字(如果可用)(比长轮询更有效),然后在没有Web套接字的情况下回退到长轮询。
有许多方法可以解决通知可能未连接到发起通知的服务器的用户的问题:
当用户连接时,它们被负载平衡到随机服务器,但是它们最终连接到哪个服务器存储在中央数据库(例如,可能是redis存储)中,任何服务器都可以从中找出任何服务器用户当前已连接到。这使您能够查找当前连接到任何用户的服务器。处理用户连接的每个服务器只是将每个用户添加到数据库时,在连接时引用其服务器ID,并在用户断开连接时将其从数据库中删除。注意:由于此信息不需要永久存储到磁盘并且数据大小很小,因此您可以选择擅长将大部分或全部信息保留在内存中的数据库。
基于用户的一些众所周知的特征(例如其userID),计算散列值并创建可重复算法以在服务器池中映射散列值。这是一个可预测的任务。因此,当服务器想要通知Bob时,他们可以调用相同的功能来确定Bob连接到哪个服务器。散列算法可以是自适应的,这样如果今天你有三台服务器,散列用户在三台服务器之间均匀分布,如果明天有四台服务器,那么散列用户将均匀分布在四台服务器中。
由于低活动的websockets目前可扩展性很强,所有用户都可以连接到所有服务器,因此每个服务器都有一个与用户的套接字连接。这是一个更简单的基础架构,但最终不具备可扩展性。
答案 1 :(得分:0)
长轮询方法会给客户端带来定期请求的负担 - 因此它们是单独的请求。 Long polling没有“通知客户”。客户轮询。
您可以使用分布式缓存来存储A和B都可以访问的中间状态信息。因此,服务器A和B可以参与与客户端的对话,因为它全部保存在该分布式缓存中。
Client Alpha Request 1 -> Node A =) Cache it as k,v (Aplha, State<-has request info)
同时,一个或多个节点A,B,C或D在其上工作并花费自己的时间。
Client Alpha Request 2 -> Node B =) Retrieve Cache it as k,v (Aplha,State <-not done)
(are we done yet?)
与此同时,一个人完成了工作。您的请求已完成:)即
节点X =)更新缓存(Aplha,State&lt; - results)
Client Alpha Request 2 -> Node B =) Retrieve Cache it as k,v (Aplha, State<-results)
(are we done yet?) (here you Sir - your results are now ready)
WebSockets:另一种选择是使用WebSockets而不是Long Polling
Connection between Client and Node A is persistent with bidirectional communication.