在 QUARKUS 中使用带有 GraphQlClient 的 Reactive RestEasy 时线程阻塞问题
Thread Blocked Problem when using Reactive RestEasy with GraphQlClient in QUARKUS
我正在使用 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<RevisionResponse> revisionResponse = entityRepository.createRevision(formData);
的响应,但发生了同样的错误。
有没有人遇到这些问题,我是否为非阻塞处理配置了错误?
谢谢。
因为您要从您的方法返回 Uni
,RESTEasy Reactive 是 运行 事件循环中的方法(有关详细信息,请参阅 this)。
但是,看起来对 entityRepository.createRevision
的调用正在阻塞 IO,这意味着事件循环线程正在被阻塞 - 这是不允许发生的事情。
使用 @Blocking
注释意味着请求正在工作池线程上提供服务,您可以在该线程上进行阻塞。
对于那些和我有同样问题的人,我通过用 Uni 包装阻塞代码来修复它:
Uni<RevisionResponse> revisionResponse = Uni.createForm().item(entityRepository.createRevision(formData));
我正在使用 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<RevisionResponse> revisionResponse = entityRepository.createRevision(formData);
的响应,但发生了同样的错误。
有没有人遇到这些问题,我是否为非阻塞处理配置了错误?
谢谢。
因为您要从您的方法返回 Uni
,RESTEasy Reactive 是 运行 事件循环中的方法(有关详细信息,请参阅 this)。
但是,看起来对 entityRepository.createRevision
的调用正在阻塞 IO,这意味着事件循环线程正在被阻塞 - 这是不允许发生的事情。
使用 @Blocking
注释意味着请求正在工作池线程上提供服务,您可以在该线程上进行阻塞。
对于那些和我有同样问题的人,我通过用 Uni 包装阻塞代码来修复它:
Uni<RevisionResponse> revisionResponse = Uni.createForm().item(entityRepository.createRevision(formData));