【问题标题】:Thread Blocked Problem when using Reactive RestEasy with GraphQlClient in QUARKUS在 QUARKUS 中使用 Reactive RestEasy 和 GraphQlClient 时出现线程阻塞问题
【发布时间】:2021-10-18 02:47:52
【问题描述】:

我使用的是 quarkus 版本2.3.0.Final

我在Controller 层中有一个休息端点:

    @POST
    @Path("/upload")
    @Produces(MediaType.APPLICATION_JSON)
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Uni<Response> uploadFile(@MultipartForm FormData formData) {

        return documentService.uploadFile(formData).onItem()
                .transform(value -> Response.status(200)
                        .entity(value)
                        .build());
    }

service 层中的代码


public Uni<?> uploadFile(@NonNull FormData formData) throws Exception {
   // Call to graphQl client using blocking process - the problem occurs here,

   RevisionResponse revisionResponse = entityRepository.createRevision(formData);

   // Do upload to s3 using s3 Async
   return Uni.createFrom()
               .future(
                    storageProviderFactory.getDefaultStorageProvider().upload(formData)))
               .map(storageUploadResponse -> DocumentResponse.builder()
                        .id(revisionResponse.getId())
                        .entityMasterId(revisionResponse.getEntityMasterId())
                        .type(revisionResponse.getType())
                        .path(formData.getFilePath())
                        .description(formData.getDescription())
                        .build());

}

这是我使用的依赖项:

    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-smallrye-graphql-client</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-reactive</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-reactive-jsonb</artifactId>
    </dependency>

当我运行这个函数时,它被entityRepository.createRevision(formData) 阻塞(控制台显示了graphql请求日志,但实际上,请求甚至没有到达目标graphql端点)

但是,如果我在controller 层中添加注释@Blocking,一切都会按预期工作。

我也尝试使用Uni 响应Uni&lt;RevisionResponse&gt; revisionResponse = entityRepository.createRevision(formData);,但发生了同样的错误。

有人遇到这些问题吗,我是不是为非阻塞处理配置了错误?

谢谢。

【问题讨论】:

    标签: java resteasy quarkus reactive graphql-java


    【解决方案1】:

    对于那些和我遇到同样问题的人,我通过用 Uni 包装阻塞代码来解决它:

    Uni&lt;RevisionResponse&gt; revisionResponse = Uni.createForm().item(entityRepository.createRevision(formData));

    参考链接:https://smallrye.io/smallrye-mutiny/guides/imperative-to-reactive#running-blocking-code-on-subscription

    【讨论】:

      【解决方案2】:

      因为你从你的方法返回Uni,RESTEasy Reactive 正在事件循环上运行该方法(有关详细信息,请参阅this)。 但是,看起来对 entityRepository.createRevision 的调用正在阻塞 IO,这意味着事件循环线程正在被阻塞——这是不允许发生的事情。

      使用@Blocking 注释意味着请求正在工作池线程上提供服务,您可以在该线程上进行阻塞。

      【讨论】:

      • 嗨@geoand,感谢您的回复。我也在想,有没有办法解决这个问题?我希望我的流程是非阻塞的。我也尝试使用非阻塞 graphql 客户端(返回 Uni 响应),但错误仍然发生。
      • Uni uni = Uni.createFrom() .item(this::invokeRemoteServiceUsingBlockingIO) .runSubscriptionOn(Infrastructure.getDefaultWorkerPool());看来这段代码可以提供帮助。更多信息:smallrye.io/smallrye-mutiny/guides/…
      • 您将需要使用存储库的非阻塞 IO 版本。
      猜你喜欢
      • 1970-01-01
      • 2021-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-02
      相关资源
      最近更新 更多