RPC через STOMP с использованием Spring и правильная обработка ошибок на стороне сервера, передаваемых клиентам

Мне нужно реализовать RPC через STOMP, где клиент работает с javascript в браузере, а на стороне сервера реализованы возможности обмена сообщениями Spring.

Хотя использование @MessageMapping подходит для обычного обмена сообщениями, я считаю использование @SendToUser весьма ограничивающим для реализации RPC, потому что клиенту трудно понять, какой ответ связан с каким запросом в сценарии, когда от клиента отправляются несколько одновременных запросов.

Конечно, нет проблем, когда делается только один запрос, и клиент ожидает его ответа, но проблемы возникают, когда клиенту приходится отслеживать несколько «открытых» вызовов rpc.

Мне удалось сделать систему в основном хорошей, связав идентификатор с каждым запросом, то есть: клиент отправляет идентификатор вместе с сообщением, а сервер отвечает специальной оболочкой сообщения, содержащей этот идентификатор, поэтому клиент может связывать асинхронные ответы с запросами.

Это нормально работает, но имеет несколько ограничений:

  • Мне нужно разработать код, который должен понимать эту структуру, и который не позволяет использовать простые аннотированные методы.

  • когда код на стороне сервера генерирует исключение, вызывается Spring @MessageExceptionHandler и клиенту возвращается правильное исключение, но идентификатор запроса теряется, потому что у обработчика нет (простого) способа доступа к нему.

Я знаю, что с rabbitmq мы можем добавить заголовок «reply-to» к каждому запросу, который должен быть связан со специальным ответом (ответом rpc), и это реализуется путем создания специальной временной очереди, на которую пользователь автоматически подписывается, но как я могу использовать эту схему весной? Кроме того, это свяжет меня с конкретным брокером.

Как я могу элегантно реализовать в Spring правильный вызов RPC, который правильно обрабатывает исключения на стороне сервера?

Я считаю, что это общая проблема, и я думаю, что Spring может значительно выиграть, если будет реализовывать ее изначально.


person Alessandro Polverini    schedule 28.07.2014    source источник
comment
Предварительное решение, требующее модификации класса Spring, описано здесь: github.com / spring-projects / spring-framework / pull / 612 Меня все еще интересует решение, не требующее модификации Spring   -  person Alessandro Polverini    schedule 02.08.2014


Ответы (2)


Это не совсем то, что вам нужно, но, возможно, вы можете попробовать что-то вроде этого: Переменные пути в Spring WebSockets @SendTo mapping

Вы определяете идентификатор на своем клиенте и отправляете идентификатор в очередь / пользователя / очередь / {myid}. На стороне сервера у вас будет класс, который выглядит следующим образом:

@MessageMapping("/user/queue/{myid}")
public void simple(@DestinationVariable String id, Object requestDto) {
    simpMessagingTemplate.convertAndSendToUser(userId, "/user/queue/" + id, responseDto);
}

Это решение может работать по тому же принципу, что и упомянутое вами решение rabbit mq.

Надеюсь это поможет.

person Oreste Viron    schedule 13.06.2016
comment
Спасибо за подсказку, но это не то, что я ищу из-за необходимости вручную обрабатывать переменную myid: это должно быть сделано фреймворком. - person Alessandro Polverini; 13.06.2016
comment
Мое решение похоже на решение кролика mq. Но вы проголосовали против меня. Не круто. - person Oreste Viron; 13.06.2016
comment
Это было ошибкой, извините. Пожалуйста, отредактируйте ответ, добавив эту информацию о rabbitmq, я отменю голосование против. - person Alessandro Polverini; 13.06.2016

Если вам не нужно исключение / причина на клиенте, а нужно только знать, какое сообщение не удалось, вы можете отправлять сообщения подтверждения для успешных сообщений. Для успешных сообщений у вас всегда есть легкий доступ к идентификатору сообщения / заголовкам. По отсутствию сообщения подтверждения клиент знает, какое сообщение не удалось.

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

person Stuck    schedule 02.04.2020