背景
项目中调用第三方接口,第三方接口响应时间不稳定,并且并发越大响应时间越长,如果使用BIO模式可能会导致服务器连接占用过高,所以采用WebClient reactor模式来调用第三方接口。
网络IO模型
连接池相关配置
maxConnections:最大连接数,默认最大连接数为处理器数量*2(但最小值为16),最大只能设置为200,超过这个数值设置无效。
pendingAcquireMaxCount:等待队列大小,默认是最大连接数的2倍,等待队列pendingAcquireMaxCount调大,同时处理的任务数等于最大连接数,未被处理的任务在队列中等待处理。
pendingAcquireTimeout:任务等待超时时间,当队列中的任务等待超过pendingAcquireTimeout还获取不到连接,就会抛出异常。
测试代码
@ConfigurationProperties("web.client")
@Data
@Configuration
public class WebClientProperties {/*** 超时时间 单位秒*/private int pendingAcquireTimeout = 50;/*** 最大等待任务数* */private int pendingAcquireMaxCount = 10000;/*** 连接池最大连接数*/private int maxConnections = 1000;}
@Configuration
public class WebClientConfig {@Autowiredprivate WebClientProperties webClientProperties;@Beanpublic WebClient webClient() {//配置固定大小连接池ConnectionProvider provider = ConnectionProvider.builder("tax-core")// 等待超时时间.pendingAcquireTimeout(Duration.ofSeconds(webClientProperties.getPendingAcquireTimeout()))// 最大连接数.maxConnections(webClientProperties.getMaxConnections())// 等待队列大小.pendingAcquireMaxCount(webClientProperties.getPendingAcquireMaxCount()).build();HttpClient httpClient = HttpClient.create(provider);// 使用Reactorreturn WebClient.builder().clientConnector(new ReactorClientHttpConnector(httpClient)).build();}
}
@RestController
@Slf4j
@RequestMapping
public class WebClientTest {@Autowiredprivate WebClient webClient;AtomicInteger count = new AtomicInteger(1);Map<Integer, Long> map = new ConcurrentSkipListMap<>();/*** 模拟第三方接口* @param param* @return* @throws InterruptedException*/@PostMapping("test/client")public Integer testClient(@RequestBody Param param) throws InterruptedException {Thread.sleep(10000);return param.getSerialNo();}/*** 测试接口* @param integer* @return*/@GetMapping("test/client/get")public ResponseEntity<String> testClientPost(@RequestParam Integer integer) {for (int i = 1; i < integer + 1; i++) {Param param = new Param();param.setSerialNo(i);call(param);}return new ResponseEntity<>();}/*** 调用第三方接口* @param param*/public void call(Param param) {final Mono<Integer> monoResp = webClient.post().uri(URI.create("http://127.0.0.1:8085/test/client")).header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE).body(Mono.just(param), Param.class).retrieve().bodyToMono(Integer.class);map.put(param.getSerialNo(), System.currentTimeMillis());monoResp.subscribe((s) ->System.out.println("响应流水号:" + s + " 耗时:" + (System.currentTimeMillis() - map.get(s))+ " 响应次数:" + count.getAndIncrement()));}@Datapublic static class Param {private Integer serialNo;}
}
调试
请求数大于max-connections
配置调整
web:client:pending-acquire-timeout: 30pending-acquire-max-count: 100max-connections: 10
发送请求
日志输出
响应流水号:2 耗时:10179 响应次数:2
响应流水号:1 耗时:10343 响应次数:3
响应流水号:8 耗时:10173 响应次数:7
响应流水号:10 耗时:10170 响应次数:9
响应流水号:3 耗时:10178 响应次数:6
响应流水号:9 耗时:10172 响应次数:5
响应流水号:4 耗时:10176 响应次数:4
响应流水号:7 耗时:10173 响应次数:1
响应流水号:5 耗时:10175 响应次数:10
响应流水号:6 耗时:10175 响应次数:8
响应流水号:11 耗时:20184 响应次数:11
响应流水号:15 耗时:20178 响应次数:13
响应流水号:14 耗时:20179 响应次数:12
响应流水号:13 耗时:20179 响应次数:14
响应流水号:18 耗时:20183 响应次数:15
响应流水号:16 耗时:20184 响应次数:16
响应流水号:19 耗时:20183 响应次数:17
响应流水号:12 耗时:20186 响应次数:18
响应流水号:17 耗时:20184 响应次数:19
响应流水号:20 耗时:20182 响应次数:20
响应流水号:21 耗时:30183 响应次数:21
响应流水号:23 耗时:30183 响应次数:22
响应流水号:25 耗时:30185 响应次数:23
响应流水号:26 耗时:30185 响应次数:26
响应流水号:30 耗时:30184 响应次数:24
响应流水号:29 耗时:30184 响应次数:25
响应流水号:27 耗时:30186 响应次数:27
响应流水号:28 耗时:30185 响应次数:28
响应流水号:22 耗时:30187 响应次数:29
响应流水号:24 耗时:30187 响应次数:30
可以看到因为我配置的max-connections为10,webClient同时发起10个请求,其余请求会进入任务队列,在连接处理完一批次的请求后会继续处理任务队列中的任务,根据上面的分析是不是第一反应就是加大max-connections就可以解决高并发情况下响应耗时增长问题呢?
调大最大连接数
当然就算是使用的reactor,最大连接数也不可能是无限制的加大了,毕竟服务器资源有限,下面来测试一下
配置调整
web:client:pending-acquire-timeout: 30pending-acquire-max-count: 10000max-connections: 1000
发送请求
日志输出
响应流水号:12 耗时:10224 响应次数:2
····省略中间日志····
响应流水号:430 耗时:10259 响应次数:199
响应流水号:487 耗时:10535 响应次数:200
响应流水号:402 耗时:19913 响应次数:201
响应流水号:490 耗时:19877 响应次数:202
····省略中间日志····
响应流水号:870 耗时:19983 响应次数:399
响应流水号:259 耗时:20679 响应次数:400
可以看出就算配置的max-connections为1000,每批次也只处理了200个请求。可能是spring做了限制但是没找到这段源码,先TODO一下吧。
需要等待的任务数大于pending-acquire-max-count
配置调整
web:client:pending-acquire-timeout: 60pending-acquire-max-count: 100max-connections: 10
发送请求
日志输出
reactor.core.Exceptions$ErrorCallbackNotImplemented: reactor.netty.internal.shaded.reactor.pool.PoolAcquirePendingLimitException: Pending acquire queue has reached its maximum size of 100
Caused by: reactor.netty.internal.shaded.reactor.pool.PoolAcquirePendingLimitException: Pending acquire queue has reached its maximum size of 100at reactor.netty.internal.shaded.reactor.pool.SimpleFifoPool.pendingOffer(SimpleFifoPool.java:54) ~[reactor-netty-0.9.10.RELEASE.jar:0.9.10.RELEASE]Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):|_ checkpoint ⇢ Request to POST http://127.0.0.1:8085/test/client [DefaultWebClient]
Stack trace:at reactor.netty.internal.shaded.reactor.pool.SimpleFifoPool.pendingOffer(SimpleFifoPool.java:54) ~[reactor-netty-0.9.10.RELEASE.jar:0.9.10.RELEASE]at reactor.netty.internal.shaded.reactor.pool.SimplePool.doAcquire(SimplePool.java:135) ~[reactor-netty-0.9.10.RELEASE.jar:0.9.10.RELEASE]at reactor.netty.internal.shaded.reactor.pool.AbstractPool$Borrower.request(AbstractPool.java:363) ~[reactor-netty-0.9.10.RELEASE.jar:0.9.10.RELEASE]at reactor.netty.resources.PooledConnectionProvider$DisposableAcquire.onSubscribe(PooledConnectionProvider.java:511) ~[reactor-netty-0.9.10.RELEASE.jar:0.9.10.RELEASE]at reactor.netty.internal.shaded.reactor.pool.SimplePool$QueueBorrowerMono.subscribe(SimplePool.java:381) ~[reactor-netty-0.9.10.RELEASE.jar:0.9.10.RELEASE]at reactor.netty.resources.PooledConnectionProvider.disposableAcquire(PooledConnectionProvider.java:197) ~[reactor-netty-0.9.10.RELEASE.jar:0.9.10.RELEASE]at reactor.netty.resources.PooledConnectionProvider.lambda$acquire$3(PooledConnectionProvider.java:161) ~[reactor-netty-0.9.10.RELEASE.jar:0.9.10.RELEASE]at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:57) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect.lambda$subscribe$0(HttpClientConnect.java:326) ~[reactor-netty-0.9.10.RELEASE.jar:0.9.10.RELEASE]at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:57) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at reactor.core.publisher.FluxRetryWhen.subscribe(FluxRetryWhen.java:79) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at reactor.core.publisher.MonoRetryWhen.subscribeOrReturn(MonoRetryWhen.java:46) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:57) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at reactor.netty.http.client.HttpClientConnect$MonoHttpConnect.subscribe(HttpClientConnect.java:329) ~[reactor-netty-0.9.10.RELEASE.jar:0.9.10.RELEASE]at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:52) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at reactor.core.publisher.Mono.subscribe(Mono.java:4213) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at reactor.core.publisher.Mono.subscribeWith(Mono.java:4324) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at reactor.core.publisher.Mono.subscribe(Mono.java:4184) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at reactor.core.publisher.Mono.subscribe(Mono.java:4120) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at reactor.core.publisher.Mono.subscribe(Mono.java:4067) ~[reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at com.WebClientTest.call(WebClientTest.java:77) ~[classes/:na]at com.WebClientTest.testClientPost(WebClientTest.java:58) ~[classes/:na]at com.WebClientTest$$FastClassBySpringCGLIB$$76f24429.invoke(<generated>) ~[classes/:na]at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) [spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) [spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) [spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:88) ~[spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]at com.base.aspect.ExceptionAspect.doAround(ExceptionAspect.java:42) ~[classes/:na]at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:644) [spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:633) [spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:70) [spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:175) [spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) [spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95) [spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) [spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) [spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) [spring-aop-5.2.8.RELEASE.jar:5.2.8.RELEASE]at com.WebClientTest$$EnhancerBySpringCGLIB$$9b90e3be.testClientPost(<generated>) [classes/:na]at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) [spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) [spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) [spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878) [spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792) [spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) [spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) [spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) [spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) [spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) [spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) [tomcat-embed-core-9.0.37.jar:4.0.FR]at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) [spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) [tomcat-embed-core-9.0.37.jar:4.0.FR]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) [tomcat-embed-websocket-9.0.37.jar:9.0.37]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) [spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) [spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) [spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) [spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1589) [tomcat-embed-core-9.0.37.jar:9.0.37]at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.37.jar:9.0.37]at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181]at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181]at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.37.jar:9.0.37]at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
挂起的任务队列达到其最大大小时会报错
任务等待时间超过pendingAcquireTimeout
配置调整
web:client:pending-acquire-timeout: 10pending-acquire-max-count: 100max-connections: 10
发送请求
日志输出
reactor.core.Exceptions$ErrorCallbackNotImplemented: reactor.netty.internal.shaded.reactor.pool.PoolAcquireTimeoutException: Pool#acquire(Duration) has been pending for more than the configured timeout of 10000ms
Caused by: reactor.netty.internal.shaded.reactor.pool.PoolAcquireTimeoutException: Pool#acquire(Duration) has been pending for more than the configured timeout of 10000msat reactor.netty.internal.shaded.reactor.pool.AbstractPool$Borrower.run(AbstractPool.java:346) ~[reactor-netty-0.9.10.RELEASE.jar:0.9.10.RELEASE]Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):|_ checkpoint ⇢ Request to POST http://127.0.0.1:8085/test/client [DefaultWebClient]
Stack trace:at reactor.netty.internal.shaded.reactor.pool.AbstractPool$Borrower.run(AbstractPool.java:346) ~[reactor-netty-0.9.10.RELEASE.jar:0.9.10.RELEASE]at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:68) [reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:28) [reactor-core-3.3.8.RELEASE.jar:3.3.8.RELEASE]at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266) ~[na:1.8.0_181]at java.util.concurrent.FutureTask.run(FutureTask.java) ~[na:1.8.0_181]at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$201(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_181]at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:293) ~[na:1.8.0_181]at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_181]at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_181]at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_181]响应流水号:9 耗时:10160 响应次数:1
响应流水号:3 耗时:10166 响应次数:2
响应流水号:1 耗时:10315 响应次数:3
响应流水号:7 耗时:10163 响应次数:6
响应流水号:2 耗时:10168 响应次数:8
响应流水号:6 耗时:10163 响应次数:9
响应流水号:8 耗时:10162 响应次数:5
响应流水号:5 耗时:10164 响应次数:4
响应流水号:10 耗时:10160 响应次数:10
响应流水号:4 耗时:10165 响应次数:7
使用过程中遇到的问题和解决方案
高并发情况下响应耗时增长问题
高并发情况下请求第三方接口时,响应耗时越来越长,并且是稳定增长。(使用BIO测试过第三方接口,虽然第三方接口响应较慢但是远低于NIO的耗时时长)
解决方案
搭建集群分摊流量,详见调试-请求数大于max-connections