2016-12-18 3 views
2

Предположим, что у меня есть балансировщик нагрузки (LB) перед экземплярами Vert.V (V), каждый экземпляр VertX подключен к очереди (Q), и у меня есть 1. .m Бэкэндз (BE).Соответствующий ответный обработчик с запросом в VertX

Пользователь нажимает кнопку, которая отправляет запрос или даже открывает сетевой сокет, балансировщик нагрузки пересылает запрос одному из экземпляров VertX, который запускает запрос в очередь, один из бэкендов потребляет сообщение и отправляет ответ обратно; если правильный экземпляр VertX его использует, он может найти обработчик ответа и написать ответ пользователю, если неправильный экземпляр VertX его использует, не будет обработчика ответа, чтобы написать ответ, и пользователь будет ждать бесконечно для ответ.

Смотрите этот эскиз:

enter image description here

В качестве альтернативы, V2 умирает и балансировка нагрузки переподключает пользователь V1, который означает, что даже если бы я мог отправить его обратно в тот же самом тот, который сделал запрос, это не гарантируется, что он все еще будет там, как только ответ вернется, но пользователь все еще может ждать ответа через другой экземпляр VertX.

В настоящее время я создаю GUID для каждого нового соединения, а затем, как только веб-узел подключится, сохраните обработчик websocket внутри хэш-карты с идентификатором GUID, а затем, когда BE хочет ответить, он выполняет fanout для всех экземпляров Vert.X..1, тот, который в настоящее время имеет правильный 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 идентифицировать каждое подключение к веб-соединению вместо того, чтобы поддерживать карту GUID, сопоставленную с обработчиками/обработчиками websocket?

Также, ссылаясь на изображение, есть ли способ для V3 использовать сообщение, но все же быть в состоянии написать ответ обратно обработчику websocket, который в настоящее время подключен к V2?

+1

Я не знаком с VertX, так что я может быть что-то, что в противном случае было бы очевидно, но почему бы не использовать 1..n очереди (один отсутствующий для каждого VertX (V)) или использовать очередь, которая поддерживает селектор, чтобы клиенты могли потреблять для них только сообщения (например, http://activemq.apache.org/how-do-i-consume-a-specific-message.html)? – mfulton26

+0

Мы используем RabbitMQ, я не думаю, что RabbitMQ может это сделать - другими словами, специально потреблять конкретные сообщения из одной очереди. Чтобы получить маршрутизацию в 1000 очередей, вам нужно настроить обмен темы, обмен темы ограничен 255 темами, если я правильно помню.На самом деле я искал аналогичную функцию в RabbitMQ 2 года назад: https://stackoverflow.com/questions/25489301/only-consuming-messages-with-certain-headers-using-rabbitmq-and-springamqp#25491291 Если мы использовали ActiveMQ, возможно, это было бы решением. –

+1

@JanVladimirMostert В качестве побочного вопроса, зачем вам нужна очередь (-а) в вашей «формуле»? Vert.x по умолчанию асинхронный, и если все ваши операции не блокируются и асинхронны, я думаю, что вам не нужна очередь ... а «back-end» также может быть и в виде вершин (любого типа). –

ответ

2

Что вам не хватает на диаграмме, это Vertx EventBus.

В принципе можно предположить, что ваш V1 ... Vn взаимосвязаны:

V1<->V2<->...<->Vn 

Давайте предположим, что Va принимает исходящая Q сообщение (красная линия), которая предназначена для Vb.
Затем он должен отправить его Vb, используя EventBus:

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 
    } 
}); 
+0

Итак, исходя из вашего предложения, V1 - V1000 запускается и генерирует UUID для себя, каждый из которых уведомляет другие экземпляры своего существования с помощью GUID. Когда экземпляр V777 отправляет сообщение в очередь, он включает свой собственный UUID, так что, когда экземпляр V367 потребляет ответ, он может видеть, что ответ был фактически предназначен для V777, а затем перенаправляет его на V777, а V777 завершает цикл. Если пользователь теряет связь и подключается к V12 или V777, V367 не сможет успешно отправить сообщение, а V367 начнется с V1, nope, V2, nope ..., V12, yep и завершит цикл. –

+0

Можно ли использовать контейнер VertX для контейнеров Docker? Я предположил, что мне просто нужно открыть правильный порт, чтобы он работал? –

+0

У вас есть идея. Что касается Docker, проверьте это (это также относится к оригинальному разговору Google): http://stackoverflow.com/questions/39812848/how-do-i-configure-vert-x-event-bus-to-work-across -cluster-оф-докеров-контейнеров –

Смежные вопросы