问题描述
REST客户端上的容错@ Asynchronous-annotation在Windows上导致核心转储,在MacOS上导致以下错误:
*** java.lang.instrument ASSERTION Failed ***: "!errorOutstanding" with message transform method call Failed at ./src/java.instrument/share/native/libinstrument/jplISAgent.c line: 873
受影响的版本:(Open Liberty 20.0.0.6/wlp-1.0.41.cl200620200528-0414)在OpenJDK 64位服务器VM(版本11.0.8 + 10-LTS)上
使用的功能:
[appSecurity-3.0,beanValidation-2.0,cdi-2.0,concurrent-1.0,distributedMap-1.0,ejbLite-3.2,el-3.0,jaxb-2.2,jaxrs-2.1,jaxrsClient-2.1,jdbc-4.2,jndi-1.0,jpa-2.2,jpaContainer-2.2,json-1.0,jsonb-1.0,jsonp-1.1,monitor-1.0,mpConfig-1.4,mpFaultTolerance-2.1,mpHealth-2.2,mpMetrics-2.3,mpOpenAPI-1.1,mpRestClient-1.4,requestTiming-1.0,servlet-4.0,ssl-1.0,transportSecurity-1.0].
要重现:
@ApplicationScoped
@RegisterRestClient(baseUri = "https://postman-echo.com")
public interface TestingClient {
@GET
@Asynchronous
@Path("delay/4")
@Consumes(value = MediaType.APPLICATION_JSON)
CompletionStage<Response> doesItCrashWithDelay(String dummyData);
注入:
@Inject
@RestClient
private TestingClient testingClient;
使用它:
@GET
@Path("doesitcrash")
public void doesItCrash() {
final Response response = testingClient.doesItCrashWithDelay("dummydata").toCompletableFuture().join();
logger.info(response.readEntity(String.class));
}
解决方法是让另一个CDI bean调用具有容错注释的其余客户端。但是根据此博客文章,REST客户端接口应该能够具有容错注释: https://openliberty.io/blog/2020/06/04/asynchronous-programming-microprofile-fault-tolerance.html
由于CompletionStage,已经异步的REST客户端上是否允许@Asynchronous?如前所述,所有其他注释,例如@Timeout和@Retry似乎都可以使用。
解决方法
首先,您 100% 正确,您不需要 MP Rest Client 接口方法上的 @Asynchronous
注释 - 根据 MP Rest Client specification,CompletionStage
的返回类型使其成为可能异步。如果您删除 @Asynchronous
注释,它应该可以工作。
在调查 JVM 错误消息时,我发现此 helpful post 表明此消息意味着 JVM 遇到了超大异常 - 可能是 StackOverflowError
。我的猜测是发生错误是因为现在有两种不同的异步机制(MP Rest Client 和 MP Fault Tolerance)一起玩——而且可能玩得不好。如果没有看到异常堆栈跟踪,我们将无法确定。
我首先建议删除注释并验证它是否有效 - 这可能是比使用单独的 CDI bean 更好的解决方法。接下来,我建议在 https://github.com/OpenLiberty/open-liberty/issues 打开一个问题以研究更好的整体解决方案。