Один из наших продуктов реализует следующую однонаправленную структуру веб-службы:
Server <--------------------- Middleware <---------------- Client
SOAP over JMS (queue) SOAP over HTTP
В этой модели клиенты отправляют сообщения SOAP через HTTP на наше промежуточное ПО (Progress SonicMQ). Сообщения помещаются в JMS-очереди SonicMQ, и наш сервер получает их оттуда. Однако, как видите, сервер не отправляет ответ клиенту (асинхронный JMS).
Мы хотели бы реализовать канал отклика для этой модели. Часто предлагаемое решение - создать временную очередь replyTo (на лету) в промежуточном программном обеспечении, позволяющую серверу отправлять ответ в эту очередь. Затем клиент может получить ответ, и очередь replyTo закрывается. Это звучит достаточно удобно, но, к сожалению, наши клиенты работают по обычному HTTP, а не по JMS, поэтому их клиенты не могут легко настроить очереди replyTo.
Один из подходов к достижению канала ответа в такой гибридной модели SOAP HTTP / JMS заключается в настройке промежуточного программного обеспечения для открытия очереди replyTo при каждом успешном приеме SOAP, добавления информации replyTo-queue и отправителя к сообщению SOAP и отправки сообщение в очередь, где оно будет выбрано сервером. После получения и обработки сообщения сервер может отправить ответ на указанную очередь replyTo в промежуточном программном обеспечении. Наконец, промежуточное программное обеспечение отправляет ответ (SOAP) по HTTP обратно исходному клиенту, используя данные из сообщения SOAP (данные, которые были вставлены в процедуры промежуточного программного обеспечения при первом получении запроса).
Хотя это возможно, но это звучит как хакерство. Таким образом, вопрос: есть ли более чистые способы достижения такой модели запроса / ответа в нашем случае? Конец сервера был реализован на Java.
Решение:
Progress SonicMQ поддерживает HTTP Acceptor «Content Reply Send», который позволяет легко отправлять JMS-ответ. Контент-акцептор ответа на ответ работает следующим образом:
- Acceptor получает HTTP-сообщение, отправленное клиентом
- Acceptor создает временную очередь JMS
- Acceptor создает JMS-сообщение, содержащее тело HTTP, и добавляет временную идентификацию очереди во вновь созданное JMS-сообщение
- Acceptor помещает сообщение JMS в свою очередь назначения (не во временную очередь)
- Акцептор начинает использовать временную очередь ответа
- Когда клиент выбирает сообщение из исходной очереди назначения, оно содержит установленный идентификатор очереди ответа
- Клиент потребляет сообщение
- Клиент отправляет ответ в очередь для ответа
- Акцептор получает сообщение из очереди
- Акцептор отправляет сообщение как HTTP клиенту, который первоначально отправил сообщение HTTP
Если потребитель (в нашем случае «сервер») не работает и не отправляет ответ, вызвавший тайм-аут, HTTP-акцептор Sonic отправляет клиенту сообщение HTTP с указанием тайм-аута. Это очень стандартная функция в SonicMQ. Я полагаю, что он существует и в других продуктах.
Это позволяет использовать стандартный SOAP поверх JMS (см. Ответ Скаффмана) на стороне «сервера», что позволяет избежать какого-либо пользовательского программирования в промежуточном программном обеспечении.
Я все еще вижу некоторые проблемы в модели JMS, но это определенно улучшение.
Обновление 2009-11-05:
После более тщательного изучения этой проблемы выяснилось, что мое подозрение в отношении HTTP <-> промежуточного программного обеспечения <-> JMS было актуальным.
В этой модели есть несколько критических проблем. Синхронно-асинхронная модель с промежуточным ПО просто не удобна. Либо пусть оба конца реализуют соединение JMS (которое должно качаться), либо используют HTTP на обоих концах. Смешивание их приводит только к головным болям. Из этих двух SOAP-over-HTTP проще и лучше поддерживается, чем SOAP-over-JMS.
Еще раз: если вы разрабатываете такую систему ... НЕ.