WebClient 连接池配置

本文介绍了在项目中使用WebClient调用第三方接口时,针对响应时间不稳定和并发增加导致响应耗时增长的问题,进行的连接池配置优化。包括设置最大连接数`maxConnections`、等待队列大小`pendingAcquireMaxCount`和等待超时时间`pendingAcquireTimeout`。通过调整这些参数,以及在高并发场景下考虑集群分摊流量的解决方案,以提高系统性能。
摘要由CSDN通过智能技术生成

背景

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

    @Bean
    public 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);
        // 使用Reactor
        return WebClient.builder()
                .clientConnector(new ReactorClientHttpConnector(httpClient))
                .build();
    }
}
@RestController
@Slf4j
@RequestMapping
public class WebClientTest {

    @Autowired
    private 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())
        );
    }

    @Data
    public static class Param {
        private Integer serialNo;
    }
}

调试

请求数大于max-connections

配置调整

web:
  client:
    pending-acquire-timeout: 30
    pending-acquire-max-count: 100
    max-connections: 10
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值