Armeria Client no respond encountered
See original GitHub issueArmeria Client no respond encountered, would you please help look into this issue.
Armeria version is 0.81.0
Background:
Service Provider: Thrift Based Service
service registration as below:
public static ThriftServiceRegistrationBean serviceRegistrationBean(Object serviceIfaceBean) {
String path = null;
Class<?> parent = serviceIfaceBean.getClass();
for (Class<?> iface : parent.getInterfaces()) {
if (iface.getName().endsWith("Iface")) {
path = iface.getName();
break;
}
}
requireNonNull(path, "Thrift Service must implement Iface or AsyncIface");
return new ThriftServiceRegistrationBean()
.setServiceName(serviceIfaceBean.getClass().getName())
.setService(THttpService.of(serviceIfaceBean))
.setPath("/" + path)
.setDecorators(LoggingService.newDecorator(), ServerAuthCheckDecorator.newDecorator());
}
Client:
client code as below:
public static <T> T generateClient(String endpoint, Class<T> clazz) {
endpoint = String.format("tbinary+h2c://%s/%s", endpoint, clazz.getName());
return build(endpoint, clazz);
}
private static <T> T build(String endpoint, Class<T> clazz) {
ClientBuilder builder = new ClientBuilder(endpoint);
builder.decorator(ClientAuthCheckDecorator.newDecorator());
return builder.build(clazz);
}
The Problem
when service A
call service B
, by the help of the logging, we found that, the request
didn’t reach up to service B
, and the thread
was hung up, client is waiting forever.
here is the thread dump for the hung up thread.
"armeria-common-worker-epoll-2-2" #79 daemon prio=5 os_prio=0 tid=0x00007fad0c006000 nid=0x5f waiting on condition [0x00007facfa6ea000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000f252edf0> (a java.util.concurrent.CompletableFuture$Signaller)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.CompletableFuture$Signaller.block(CompletableFuture.java:1693)
at java.util.concurrent.ForkJoinPool.managedBlock(ForkJoinPool.java:3323)
at java.util.concurrent.CompletableFuture.waitingGet(CompletableFuture.java:1729)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at com.linecorp.armeria.client.thrift.THttpClientInvocationHandler.invokeClientMethod(THttpClientInvocationHandler.java:135)
at com.linecorp.armeria.client.thrift.THttpClientInvocationHandler.invoke(THttpClientInvocationHandler.java:85)
at com.sun.proxy.$Proxy68.getOrgThirdPartResConfig(Unknown Source)
at com.hnair.phoenix.mgmt.services.project.domain.service.impl.ApplicationServiceImpl.sendCreatApplicationEvent(ApplicationServiceImpl.java:129)
at com.hnair.phoenix.mgmt.services.project.domain.service.impl.ApplicationServiceImpl.createApplication(ApplicationServiceImpl.java:110)
at com.hnair.phoenix.mgmt.services.project.domain.service.impl.ApplicationServiceImpl$$FastClassBySpringCGLIB$$94c5215e.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:684)
at com.hnair.phoenix.mgmt.services.project.domain.service.impl.ApplicationServiceImpl$$EnhancerBySpringCGLIB$$49a6a3f4.createApplication(<generated>)
at com.hnair.phoenix.mgmt.services.project.interfaces.facade.impl.ApplicationServiceFacadeImpl.createApplication(ApplicationServiceFacadeImpl.java:54)
at com.hnair.phoenix.mgmt.services.project.api.ApplicationServiceAsyncApi.createApplication(ApplicationServiceAsyncApi.java:68)
at com.hnair.phoenix.services.project.v1.ApplicationService$AsyncProcessor$createApplication.start(ApplicationService.java:1342)
at com.hnair.phoenix.services.project.v1.ApplicationService$AsyncProcessor$createApplication.start(ApplicationService.java:1280)
at com.linecorp.armeria.server.thrift.ThriftCallService.invokeAsynchronously(ThriftCallService.java:162)
at com.linecorp.armeria.server.thrift.ThriftCallService.invoke(ThriftCallService.java:145)
at com.linecorp.armeria.server.thrift.ThriftCallService.serve(ThriftCallService.java:129)
at com.linecorp.armeria.server.thrift.ThriftCallService.serve(ThriftCallService.java:52)
at com.linecorp.armeria.server.thrift.THttpService.invoke(THttpService.java:605)
at com.linecorp.armeria.server.thrift.THttpService.decodeAndInvoke(THttpService.java:580)
at com.linecorp.armeria.server.thrift.THttpService.lambda$doPost$3(THttpService.java:434)
at com.linecorp.armeria.server.thrift.THttpService$$Lambda$631/883285835.apply(Unknown Source)
at java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:822)
at java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:797)
at java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:474)
at java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:1962)
at com.linecorp.armeria.common.HttpMessageAggregator.apply(HttpMessageAggregator.java:151)
at com.linecorp.armeria.common.HttpMessageAggregator.apply(HttpMessageAggregator.java:36)
at java.util.concurrent.CompletableFuture.uniHandle(CompletableFuture.java:822)
at java.util.concurrent.CompletableFuture$UniHandle.tryFire(CompletableFuture.java:797)
at java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:442)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:333)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:905)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
The current workaround
At the moment, we setup the timeout for the client as following. It’s curious that why the request didn’t send out, and no exception occured, but the thread is still waiting for the response.
private static <T> T build(String endpoint, Class<T> clazz) {
ClientBuilder builder = new ClientBuilder(endpoint);
builder.defaultWriteTimeoutMillis(1000L)
.defaultResponseTimeoutMillis(5000)
.decorator(ClientAuthCheckDecorator.newDecorator());
return builder.build(clazz);
}
Issue Analytics
- State:
- Created 4 years ago
- Comments:19 (6 by maintainers)
Top Results From Across the Web
Client-side load balancing and service discovery
There are 3 elements involved in client-side load balancing in Armeria: ... If an Endpoint responds with non-200 status code or does not...
Read more >Index (Armeria 0.69.0 API reference) - Javadoc.io
The Function that decorates the client components. decorator(DecoratingClientFunction<HttpRequest, HttpResponse>) - Method in class com.linecorp.armeria.client.
Read more >Pattern for rich error handling in gRPC - Stack Overflow
It seems that in most client languages, an error results in an exception being thrown, with no way to grab the response. For...
Read more >Error handling — tapir 1.x documentation - SoftwareMill
Should the request be completed with a 400 Bad Request response, or should the ... instead of a no-match (ultimately leading to a...
Read more >Building a gRPC Client Standard to Boost Reliability and ...
A problem we faced fitting our requirements through Armeria is that we wanted services to be able to vary parameter values across methods...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
after discussion with @hyangtack , we infer the root cause is, the
blocking
api call used up thearmeria worker threads
, so there is no thread to send request to service provider, then this issue happened. thanks @hyangtack for your kindness support.Spring Bean Configuration
Spring MVC Controller to use the
ProjectService.AsyncIface
after call
asyncProjectSrv.isNameAvailable
, the service provider didn’t receive the request(here is the problem)A client decorator to fill context info, and pass it to the service provider.