Цикл событий блоков потоковых файлов?

#micronaut #micronaut-rest

Вопрос:

Проект в micronaut 2.0.1 имеет функцию предоставления некоторого ресурса. Ресурс передается потоком ввода из другой службы по протоколу HTTP.

 @ExecuteOn(TaskExecutors.IO)
@Status(HttpStatus.OK)
@Get
public StreamedFile export() throws FileNotFoundException {
    InputStream is = service.getFromOtherServiceByHttpCall();
    return new StreamedFile(is, CSV_MEDIA_TYPE);    
}
 

К сожалению, приложение перезапускается, потому что конечная точка работоспособности возвращается недостаточно быстро.

Возможно ли, что StreamedFile блокирует цикл событий при возврате файла через Интернет? Локально все работает.


Редактировать:

Я думаю, что нашел решение для возврата строкового файла, но, к сожалению, оно значительно медленнее.

 public Flux<String> export() throws FileNotFoundException {

    InputStream is = service.getFromOtherServiceByHttpCall();

    return Flux.using(() -> new BufferedReader(new InputStreamReader(is)).lines(),
            Flux::fromStream,
            BaseStream::close
    ).subscribeOn(Schedulers.boundedElastic());
 

Я все еще не понимаю, как правильно передавать байтовый ресурс.

Ответ №1:

Блокировка потока цикла событий может быть вашим случаем, даже если этого не должно произойти, если вы каким-то образом не запускаете только один поток цикла событий.

Тем не менее, вам следует лучше передать содержимое извлеченного файла в другой отдельный поток, используя / StreamedFile PipedOutputStream PipedInputStream :

 @Controller("/file")
public class FileHandlerController {

    private ExecutorService ioExecutor;
    private OtherService service;

    public FileHandlerController(@Named("io") ExecutorService executorService, OtherService service) {
        this.ioExecutor = executorService; // make sure to pipe on a separate thread so that the file gets returned immediately
        this.service = service;
    }

    @Status(HttpStatus.OK)
    @Get
    public StreamedFile export() throws FileNotFoundException {
        PipedOutputStream output = new PipedOutputStream();
        PipedInputStream input = new PipedInputStream(output);
        executorService.execute(() -> {
            InputStream is = service.getFromOtherServiceByHttpCall();
            int b;
            while((b = is.read()) != -1) {
                output.write(b);
            }
            output.flush();
            output.close();
        });
        return new StreamedFile(input, CSV_MEDIA_TYPE);
    }
}