Приходилось встречаться с решениями, в которых отсутствует именно потоковая передача файла, т.е. приложение полностью сохраняет файл в оперативную память прежде чем записать его в конечную систему (например, в MQ очередь). В результате, приложение накладывает ограничение на размер передаваемого файла, а загрузка ресурсов не только снижает пропускную способность, но и может привести к падению системы из-за нехватки памяти.
В частности, такое решение, как IBM Integration Bus до сих пор не позволяет в потоковом режиме сохранить получаемый файл по REST протоколу и записать его в MQ очередь.
В статье хотелось продемонстрировать способ, которым я воспользовался для решения такой задачи. Возможно, кому-то будет полезно.
Спасибо за развернутые замечания и предлагаемые решения!
Согласен с Вами, что приведенный код не отвечает требованиям по надежности в случае нештатных ситуаций. В статье я бы не хотел усложнять код обработкой такого рода ошибок, а как можно проще продемонстрировать библиотеки и классы, используемые для решения такой задачи.
Задача статьи состоит в демонстрации способа потоковой передачи файла между REST сервисом и системой обмена сообщениями (MQ). Описанный вначале статьи сценарий служит для иллюстрации ситуации, в которой может возникнуть такая потребность.
Чтобы не усложнять статью и не отвлекаться от её основной задачи был приведен код сервиса, выполняющего минимальный набор операций, позволяющих продемонстрировать каким образом осуществляется потоковое сохранение файла из REST запроса в очередь MQ, а также как можно вернуть в REST-ответ файл, хранящийся в MQ очереди.
В рамках демонстрационного сервиса, метод upload получает файл от клиента и сохраняет его в MQ очередь, в которой эти сообщения дальше никуда не отправляются. Метод download считывает эти сообщения и возвращает в виде ответа клиенту.
В промышленном сценарии сообщения отправляются в целевую сеть, где считываются приложением и записываются в хранилище, например, в систему электронного документооборота, после чего возвращают клиенту, например, идентификатор файла. При запросе файла, клиент передает этот идентификатор REST сервису, который отправляет его через систему обмена сообщениями в приложение, которое считывает из хранилища этот файл и помещает его в MQ, после чего REST-сервис отправляет полученный набор сообщений из MQ в REST ответа в виде файла.
Если более детально рассматривать промышленный сценарий, то это могло бы выглядеть так: Сценарий отправки файла от клиента:
Клиент отправляет файл в REST сервис.
REST сервис в потоковом режиме сохраняет файл в очередь MQ «CONTENT.TO.STORE» в виде набора сообщений.
REST сервис формирует сообщение, указывая мета информацию о файле (например, наименование, размер, идентификатор группы сообщений), и отправляет в очередь MQ «REQUEST.TO.STORE».
MQ передает эти сообщения в целевые очереди, находящуюся в территориально удаленной сети.
На той стороне приложение Application прослушивает очередь «REQUEST.TO.STORE» (например, через Message-Driven Bean), получая мета информацию о пересланном файле.
Приложение по полученному идентификатору группы сообщений считывает из очереди «CONTENT.TO.STORE» содержимое файла и сохраняет его в своем хранилище.
Приложение формирует сообщение с идентификатором файла, которое было присвоено в этом хранилище, и отправляет его в очередь MQ «RESPONSE.TO.STORE».
MQ передает это сообщение обратно в сеть, где размещен REST сервис, который ожидает ответного сообщения из очереди «RESPONSE.TO.STORE».
REST сервис, получив ответ – возвращает клиенту идентификатор файла.
Сценарий запроса файла:
Клиент отправляет в REST сервис идентификатор файла.
REST сервис формирует сообщение, указывая полученный идентификатор файла и отправляет в очередь MQ «REQUEST.TO.RETRIEVE».
MQ передает сообщение в сеть, где размещается приложение Application.
Приложение Application, получив сообщение из очереди «REQUEST.TO.RETRIEVE», по полученному идентификатору считывает файл из хранилища и записывает в очередь MQ «CONTENT.TO.RETRIEVE».
Приложение Application формирует сообщение с метаинформацией о файле (имя, размер, идентификатор группы сообщений) и отправляет в очередь «RESPONSE.TO.RETRIEVE».
MQ передает эти сообщения обратно в сеть, где размещен REST сервис, ожидающий ответного сообщения из очереди «RESPONSE.TO.RETRIEVE».
REST сервис считывает по идентификатору группы сообщений содержимое файла из очереди «CONTENT.TO.RETRIEVE» и отправляет в виде ответа клиенту.
В частности, такое решение, как IBM Integration Bus до сих пор не позволяет в потоковом режиме сохранить получаемый файл по REST протоколу и записать его в MQ очередь.
В статье хотелось продемонстрировать способ, которым я воспользовался для решения такой задачи. Возможно, кому-то будет полезно.
Согласен с Вами, что приведенный код не отвечает требованиям по надежности в случае нештатных ситуаций. В статье я бы не хотел усложнять код обработкой такого рода ошибок, а как можно проще продемонстрировать библиотеки и классы, используемые для решения такой задачи.
Задача статьи состоит в демонстрации способа потоковой передачи файла между REST сервисом и системой обмена сообщениями (MQ). Описанный вначале статьи сценарий служит для иллюстрации ситуации, в которой может возникнуть такая потребность.
Чтобы не усложнять статью и не отвлекаться от её основной задачи был приведен код сервиса, выполняющего минимальный набор операций, позволяющих продемонстрировать каким образом осуществляется потоковое сохранение файла из REST запроса в очередь MQ, а также как можно вернуть в REST-ответ файл, хранящийся в MQ очереди.
В рамках демонстрационного сервиса, метод upload получает файл от клиента и сохраняет его в MQ очередь, в которой эти сообщения дальше никуда не отправляются. Метод download считывает эти сообщения и возвращает в виде ответа клиенту.
В промышленном сценарии сообщения отправляются в целевую сеть, где считываются приложением и записываются в хранилище, например, в систему электронного документооборота, после чего возвращают клиенту, например, идентификатор файла. При запросе файла, клиент передает этот идентификатор REST сервису, который отправляет его через систему обмена сообщениями в приложение, которое считывает из хранилища этот файл и помещает его в MQ, после чего REST-сервис отправляет полученный набор сообщений из MQ в REST ответа в виде файла.
Если более детально рассматривать промышленный сценарий, то это могло бы выглядеть так:
Сценарий отправки файла от клиента:
Сценарий запроса файла: