WebClient 连接池配置

article/2025/9/12 6:21:55

背景

项目中调用第三方接口,第三方接口响应时间不稳定,并且并发越大响应时间越长,如果使用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


http://chatgpt.dhexx.cn/article/7ar3h41n.shtml

相关文章

WebClient用法小结

进来的项目中要实现能够在windows service中调用指定项目的链接页面。由于访问页面时候使用的是ie浏览器或其他浏览器&#xff0c;所以想起用webclient类。 如果只想从特定的URI请求文件&#xff0c;则使用WebClient&#xff0c;它是最简单的.NET类&#xff0c;它只用一两条命…

WebClient类的使用方法(C#---网络编程)

WebClient类的使用方法&#xff08;C#---网络编程&#xff09; 1、WebClient类 WebClient类提供向URI标识的任何本地、Intranet或Internet资源发送数据以及从这些资源接收数据的公共方法。 默认情况下&#xff0c;WebClient实例不能发送可选的HTTP报头。如果要发送可选报头&a…

WebClient 用法总结

一、WebClient概述 WebClient提供向 URI 标识的资源发送数据和从 URI 标识的资源接收数据的公共方法&#xff0c; WebClient 类提供向 URI 标识的任何本地、Intranet 或 Internet 资源发送数据以及从这些资源接收数据的公共方法。 WebClient 类使用 WebRequest 类提供对资源…

C#-WebClient

using ( var wc new System.Net.WebClient() ) {var imagebytes wc.DownloadData( hag.ImagePath );using ( MemoryStream ms new MemoryStream( imagebytes ) ) {picImage.Image Image.FromStream( ms );} } C#中HttpWebRequest、WebClient、HttpClient的使用 HttpWebRe…

webclient学习1.webclient是什么?

1.webclient是什么&#xff1f; WebClient 软件包是 RT-Thread 自主研发的&#xff0c;基于 HTTP 协议的客户端的实现&#xff0c;它提供设备与 HTTP Server 的通讯的基本功能。 2.软件包功能特点 WebClient 软件包功能特点&#xff1a; 支持 IPV4/IPV6 地址 WebClient 软…

SpringBoot - 网络请求客户端WebClient使用详解

在 Spring 5 之前&#xff0c;如果我们想要调用其他系统提供的 HTTP 服务&#xff0c;通常可以使用 Spring 提供的 RestTemplate 来访问&#xff0c;不过由于 RestTemplate 是 Spring 3 中引入的同步阻塞式 HTTP 客户端&#xff0c;因此存在一定性能瓶颈。根据 Spring 官方文档…

【QString 函数学习篇】

【QString 函数学习篇】 【1】UI设计布局【2】QChar | setAlignment |【3】sprintf | asprintf | setNum | number |【4】toInt | toUpper [十进制->十六进制 | 十进制->二进制]【5】clear | append【6】二进制->十六进制 | 二进制->十进制【7】prepend【8】strimm…

Qt扫盲-QString使用总结

QString使用总结 一、概述二、初始化字符串1、极速版2、原理版 三、操作字符串1、极速版1. 增加2. 删除3. 修改4. 插入5. 转换 2、原理版 四、查询字符串五、字符串格式转换六、Null 字符串和 Empty 字符串的区别七、字符串参数格式化八、更高效的字符串构造九、最大大小和出现…

Qt之QString字符串类的详细介绍及功能函数示例用法

前序&#xff1a;为了加深对Qt各个类的认识和了解&#xff0c;决定以后再闲暇的时间对Qt类进行详细的阅读&#xff08;基于Qt cteater 的帮助文档&#xff09;&#xff0c;这样既可以提高自己的英文阅读能力&#xff0c;也可以对各个类有一个更加深入的认识和了解。 注&#xf…

QString类详解

文章目录 一、简要介绍1.1 隐式共享 二、常用方法2.1 常用构造函数2.2 字符串与数值之间的转换2.3 添加字符串2.4 大小写转换2.5 长度2.6 其他常用函数 一、简要介绍 在Qt中表示字符串的类是QString类&#xff0c;它存储字符串是采用的Unicode码&#xff0c;编码方式是使用UTF…

QString(详解)

目录 一、QString转char* 二、合并字符串 三、分割字符串 split()函数 mid(pos,n)函数 QString::section truncate(int)函数&#xff0c;从指定位置截断字符串str 四、去除字符串两端的空白 QString::trimmed()函数 QString::simplified()函数 五、查找是否包含字符…

Java——JLabel自动换行问题

┏(ω)☞ 本专栏的目录&#xff08;为您提供更好的查询方式&#xff09;&#xff08;点这里说不定有你想要的&#xff09; JLabel类可显示文本&#xff0c;一般直接添加文字会导致如下问题&#xff08;字体显示不全&#xff09;&#xff0c;在不同过增加文本框的长度的情况下可…

JLabel展示文本和图片

JLabel 构造方法 JLabel&#xff08;&#xff09;创建一个不含图像&#xff0c;不含文本的 JLabel 对象 JLabel&#xff08;String text&#xff09;使用指定的文本创建一个 JLabel 对象 JLabel&#xff08;Icon image&#xff09;创建一个具有指定图像的 JLabel 对象 pack…

java设置JLabel字体字号颜色

JLabel jl; Font f new Font("宋体",Font.PLAIN,16); jl.setFont(f); jl.setForeground(Color.red); 效果图&#xff1a;

JLabel设置背景颜色和设置文字颜色

JLabel设置背景颜色&#xff1a; JLabel light1 new JLabel("wuli"); light1.setOpaque(true); //此句是重点&#xff0c;设置背景颜色必须先将它设置为不透明的&#xff0c;因为默认是透明的。。。 light1.setBackground(Color.GREEN); JLabel设置文字颜色&…

【Java|Swing】关于JLabel换行

最近在用Swing做Windows的窗口程序&#xff0c;在使用JLabel时发现使用\n没办法换行&#xff0c;于是乎借助百度一下弄懂了JLabel是如何实现换行的。 先可以看一下使用\n的效果 JLabel labelnew JLabel("数据版本\nv1.0.0"); 运行测试 很明显&#xff0c;换行失败了…

初识JFrame、JPanel、JLabel

JFrame&#xff1a;java图形化界面设计&#xff0c;是一个顶层的框架类&#xff0c;相当于容器。好比一个窗户的框子&#xff0c;这个框子可以嵌入几个玻璃窗。 JPanel&#xff1a;也是一个容器类&#xff0c;相当于一个大玻璃窗。 JLabel&#xff1a;是一些基础组件&#xff0…

JFrame,JPanel,JLabel详解

JFrame是一个顶层的框架类&#xff0c;好比一个窗户的框子。也是一个容器类。这个框子可以嵌入几个玻璃窗。 JPanel是一个容器类&#xff0c;相当于一大玻璃窗。 JLabel等是一些基础组件&#xff0c;它必须置于某个容器里&#xff0c;类似于窗花、剪纸&#xff0c;必须置于窗户…

Java图形界面之JFrame,JLabel,JButton

Java图形界面之JFrame&#xff0c;JLabel&#xff0c;JButton 前言 ​ Java第一卷​ 图形界面第一节 JFrame package Demo03;import javax.swing.*; import java.awt.*;public class JFrame01 {public static void main(String[] args) {JFrame f new JFrame("第一个Swi…

Java GUI编程4---标签组件JLabel

1. 认识JLabel JLabel组件表示的是一个标签&#xff0c;本身是用于显示信息的&#xff0c;一般情况下是不能直接更改器显示内容的。创建完的Label对象可以通过Container类中的add()方法&#xff0c;加入到容器中&#xff0c;JLabel类的常用方法和常量如下表所示。 序号常量描…