假设我在1..n VertX(V)实例前面有一个负载均衡器(LB),每个VertX实例都连接到一个队列(Q),我有1..m后端(BE)。
用户点击发出帖子请求的按钮甚至打开网络套接字,负载均衡器将请求转发给其中一个VertX实例,该实例向队列发出请求,其中一个后端使用该消息,发回一个回复;如果正确的VertX实例使用它,它可以查找响应处理程序并向用户写入响应,如果错误的VertX实例使用它,则不会有响应处理程序来写入响应,用户将无限期地等待回应。
见这个草图:
或者,V2死机并且负载均衡器将用户重新连接到V1,这意味着即使我可以将其发送回发出请求的完全相同的一个,但是一旦响应返回,它不能保证仍然在那里,但是用户可能仍在等待通过另一个VertX实例的响应。
我目前正在做的是为每个新连接生成一个GUID,然后一旦websocket连接,就将websocket处理程序存储在一个针对GUID的hashmap中,然后当BE想要响应时,它会进行扇出对于所有1..n VertX实例,当前在其hashmap中具有正确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处理程序/后处理程序的GUID映射?
另外,参考图片,有没有办法让V3使用该消息,但是仍然可以将响应写回当前连接到V2的websocket处理程序?
答案 0 :(得分:2)
您的图表中缺少的是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
}
});