0

micronaut 2.0.1 中的项目具有公开某些资源的功能。资源通过 HTTP 与来自另一个服务的 InputStream 一起流式传输。

@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());

我仍然不明白如何正确流式传输字节资源。

4

1 回答 1

0

阻塞事件循环线程可能是你的情况,即使这不应该发生,除非你以某种方式只启动一个单一的事件循环线程。

不过,您最好使用/将拉取的文件内容通过管道传输到StreamedFile另一个单独的线程:PipedOutputStreamPipedInputStream

@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);
    }
}
于 2021-10-02T12:27:15.583 回答