Closed gordanyang closed 5 years ago
I am almost sure the problem occurs because the mapping is in async mode and the code that is creating a TaskExecutor
is, see CharonConfiguration:
@Bean
@ConditionalOnMissingBean
public TaskExecutor charonTaskExecutor() {
if (isAsynchronousMappingPresent()) {
return new ThreadPoolTaskExecutor();
}
return null;
}
The default ThreadPoolTaskExecutor
has no limits on thread pool.
Maybe the TaskExecutor
configuration should be exposed as yml properties.
For a quick fix you could just override the TaskExecutor
bean creating a custom bean and defining the thread pool limits.
Could you please run your test with asynchronous: false
?
Also note that the destination should be only http://localhost:9092 without path and for saving the path in forward request you should set the strip-path
property to false
BTW. The current configuration properties list is a little bit different now: https://github.com/mkopylec/charon-spring-boot-starter#configuration-properties-list
charon:
filter-order: 100000
timeout:
connect: 5000
read: 5000
retrying:
max-attempts: 3
metrics:
enabled: false
names-prefix: charon
logging-reporter:
enabled: false
reporting-interval-in-seconds: 60
tracing:
enabled: false
mappings-update:
enabled: false
mappings:
-
name: echo
path: /api/echo/
destinations: http://localhost:9092/api/echo/
asynchronous: true
strip-path: false
benchmark test | Requests per second | Time per request |
---|---|---|
ab -n 5000 -c 20 http://localhost:8080/api/echo/hello | 1100.27/sec(mean) | 18.177 ms(mean) |
ab -n 5000 -c 20 http://localhost:9092/api/echo/hello | 2116.81/sec(mean) | 9.448 ms(mean) |
charon:
filter-order: 100000
timeout:
connect: 5000
read: 5000
retrying:
max-attempts: 3
metrics:
enabled: false
names-prefix: charon
logging-reporter:
enabled: false
reporting-interval-in-seconds: 60
tracing:
enabled: false
mappings-update:
enabled: false
mappings:
-
name: echo
path: /api/echo/
destinations: http://localhost:9092/api/echo/
asynchronous: false
strip-path: false
benchmark test | Requests per second | Time per request |
---|---|---|
ab -n 5000 -c 20 http://localhost:8080/api/echo/hello | 597.63/sec(mean) | 33.466 ms(mean) |
@Bean
@ConditionalOnMissingBean
public TaskExecutor charonTaskExecutor() {
if (isAsynchronousMappingPresent()) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2000);
executor.setMaxPoolSize(2000);
executor.setQueueCapacity(4000);
return executor;
}
return null;
}
09:52:36.306 ERROR o.a.catalina.core.ContainerBase.[Tomcat].[localhost].[/].[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
org.springframework.web.client.ResourceAccessException: I/O error on GET request for "http://localhost:9092/api/echo/hello": connection timed out: localhost/127.0.0.1:9092; nested exception is io.netty.channel.ConnectTimeoutException: connection timed out: localhost/127.0.0.1:9092
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:633)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:595)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:557)
at com.github.mkopylec.charon.core.http.RequestForwarder.sendRequest(RequestForwarder.java:101)
at com.github.mkopylec.charon.core.http.RequestForwarder.forwardHttpRequest(RequestForwarder.java:67)
at com.github.mkopylec.charon.core.http.ReverseProxyFilter.lambda$forwardToDestination$9(ReverseProxyFilter.java:117)
at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:276)
at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:157)
at com.github.mkopylec.charon.core.http.ReverseProxyFilter.forwardToDestination(ReverseProxyFilter.java:117)
at com.github.mkopylec.charon.core.http.ReverseProxyFilter.doFilterInternal(ReverseProxyFilter.java:94)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:317)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:127)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:169)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at com.gordan.puma.edge.adapters.StatelessAuthenticationFilter.doFilter(StatelessAuthenticationFilter.java:70)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:200)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:66)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:87)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:108)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:522)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.valves.RemoteIpValve.invoke(RemoteIpValve.java:677)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:1110)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:785)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1425)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: io.netty.channel.ConnectTimeoutException: connection timed out: localhost/127.0.0.1:9092
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe$1.run(AbstractNioChannel.java:220)
at io.netty.util.concurrent.PromiseTask$RunnableAdapter.call(PromiseTask.java:38)
at io.netty.util.concurrent.ScheduledFutureTask.run(ScheduledFutureTask.java:120)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:358)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:374)
at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
... 1 common frames omitted
So the problem occurs only in async mode?
In your code change @ConditionalOnMissingBean
to @Primary
and that should fix the problem.
Also your pool size is way to big. Consider the code below:
@Bean
@Primary
public TaskExecutor charonTaskExecutor() {
if (isAsynchronousMappingPresent()) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(100);
return executor;
}
return null;
}
Can you please try to run your test with 1.10.0 version?
Do you still have a problem?
about performance
charon config
echo server
use ab test
some error in console
when try to test 9092 , No error appears in the console.