将响应处理程序与 VertX 中的请求匹配
Match response handler with request in VertX
假设我在 1..n 个 VertX (V) 实例前面有一个负载均衡器 (LB),每个 VertX 实例都连接到一个队列 (Q),并且我有 1..m 个后端 (BE ).
用户点击按钮发出 post 请求甚至打开网络套接字,负载均衡器将请求转发到 VertX 实例之一,该实例向队列发出请求,其中之一后端使用消息并发回响应;如果正确的 VertX 实例使用它,它可以查找响应处理程序并向用户写入响应,如果错误的 VertX 实例使用它,则不会有响应处理程序来写入响应,用户将无限期地等待一个回应。
看这个草图:
或者,V2 死掉,负载均衡器将用户重新连接到 V1,这意味着即使我可以将它发送回发出请求的完全相同的那个,一旦响应返回,它也不能保证仍然存在,但是用户可能仍然在那里等待通过另一个 VertX 实例的响应。
我目前正在做的是为每个新连接生成一个 GUID,然后一旦 websocket 连接,就将 websocket 处理程序存储在一个针对 GUID 的哈希图中,然后当 BE 想要响应时,它就会响应对所有 1..n 个 VertX 实例的扇出,当前在其哈希图中具有正确 GUID 的实例然后可以向用户写入响应。
同样以这种方式处理 POST / GET。
伪代码:
queue.handler { q ->
q.handler {
val handler = someMap.get(q.guid)
// only respond if handler exists
if (handler != null){
handler.writeResponse(someresponsemessagehere)
}
}
}
vertx.createHttpServer().websocketHandler { ws ->
val guid = generateGUID()
someMap.put(guid, ws)
ws.writeFinalTextFrame("guid=${guid}")
ws.handler {
val guid = extractGuid(it)
// send request to BE including generated GUID
sendMessageToBE(guid, "blahblah")
}
}.requestHandler { router.accept(it) }.listen(port)
但这确实意味着如果我有 1000 个 VertX 应用程序 运行,后端将需要将其消息扇出到 1000 个前端实例,其中只有一个实例会使用该消息。
VertX 似乎已经很好地处理了异步操作,VertX 中是否有一种方法可以识别每个 websocket 连接,而不必维护映射到 websocket 处理程序/post 处理程序的 GUID 映射?
另外,参考图片,有没有办法让 V3 使用消息,但仍然能够将响应写回到当前连接到 V2 的 websocket 处理程序?
您的图中缺少的是 Vertx EventBus。
基本上你可以假设你的 V1...Vn 是相互连接的:
V1<->V2<->...<->Vn
让我们假设 Va 收到了您的出站 Q 消息(红线),该消息是针对 Vb.
然后它应该使用 EventBus 将它发送到 Vb:
eventBus.send("Vb UUID", "Message for Vb, also containing WebSocket UUID", ar -> {
if (ar.succeeded()) {
// All went well
}
else {
// Vb died or has other problems. Your choice how to handle this
}
});
假设我在 1..n 个 VertX (V) 实例前面有一个负载均衡器 (LB),每个 VertX 实例都连接到一个队列 (Q),并且我有 1..m 个后端 (BE ).
用户点击按钮发出 post 请求甚至打开网络套接字,负载均衡器将请求转发到 VertX 实例之一,该实例向队列发出请求,其中之一后端使用消息并发回响应;如果正确的 VertX 实例使用它,它可以查找响应处理程序并向用户写入响应,如果错误的 VertX 实例使用它,则不会有响应处理程序来写入响应,用户将无限期地等待一个回应。
看这个草图:
或者,V2 死掉,负载均衡器将用户重新连接到 V1,这意味着即使我可以将它发送回发出请求的完全相同的那个,一旦响应返回,它也不能保证仍然存在,但是用户可能仍然在那里等待通过另一个 VertX 实例的响应。
我目前正在做的是为每个新连接生成一个 GUID,然后一旦 websocket 连接,就将 websocket 处理程序存储在一个针对 GUID 的哈希图中,然后当 BE 想要响应时,它就会响应对所有 1..n 个 VertX 实例的扇出,当前在其哈希图中具有正确 GUID 的实例然后可以向用户写入响应。 同样以这种方式处理 POST / GET。
伪代码:
queue.handler { q ->
q.handler {
val handler = someMap.get(q.guid)
// only respond if handler exists
if (handler != null){
handler.writeResponse(someresponsemessagehere)
}
}
}
vertx.createHttpServer().websocketHandler { ws ->
val guid = generateGUID()
someMap.put(guid, ws)
ws.writeFinalTextFrame("guid=${guid}")
ws.handler {
val guid = extractGuid(it)
// send request to BE including generated GUID
sendMessageToBE(guid, "blahblah")
}
}.requestHandler { router.accept(it) }.listen(port)
但这确实意味着如果我有 1000 个 VertX 应用程序 运行,后端将需要将其消息扇出到 1000 个前端实例,其中只有一个实例会使用该消息。
VertX 似乎已经很好地处理了异步操作,VertX 中是否有一种方法可以识别每个 websocket 连接,而不必维护映射到 websocket 处理程序/post 处理程序的 GUID 映射?
另外,参考图片,有没有办法让 V3 使用消息,但仍然能够将响应写回到当前连接到 V2 的 websocket 处理程序?
您的图中缺少的是 Vertx EventBus。
基本上你可以假设你的 V1...Vn 是相互连接的:
V1<->V2<->...<->Vn
让我们假设 Va 收到了您的出站 Q 消息(红线),该消息是针对 Vb.
然后它应该使用 EventBus 将它发送到 Vb:
eventBus.send("Vb UUID", "Message for Vb, also containing WebSocket UUID", ar -> {
if (ar.succeeded()) {
// All went well
}
else {
// Vb died or has other problems. Your choice how to handle this
}
});