vertx HttpClient使用的各种坑

本文详细记录了在使用 Vert.x HttpClient 进行微服务通信时遇到的各种问题及解决方案,包括连接错误、超时设置、服务发现集成(如ServiceComb、华为CSE)等常见挑战,帮助开发者避免或解决类似问题。

vert HttpClient性能非常好,但是使用不当,就会出现非常难于定位的问题。很多问题非常严重,比如挂死,分析日志、堆栈都可能看不出任何原因。因此在写代码的时候,就需要非常注意。下面有几个排查点:

  1. 设置请求超时时间。必须合理设计超时时间,否则异常情况,会导致连接不释放。如果在response里面做其他操作,还需要重设超时时间。

    例如:

        HttpClientRequest clietRequest =

            httpClient.request(context.request().method(),

                    uri.getPort(),

                    uri.getHost(),

                    "/" + path + params).setTimeout(10000);  //设置请求超时时间

        clietRequest.handler(clientResponse -> {

            clietRequest.setTimeout(10000);  //如果解析响应还可能超时,那么也必须重设超时时间

            context.request().response().setStatusCode(clientResponse.statusCode());

            context.request().response().headers().setAll(clientResponse.headers());

            LOGGER.info("remote response begins");

            clientResponse.handler(data -> {

                context.request().response().write(data);

                LOGGER.info("remote response data transfer");

            });

            clientResponse.endHandler((v) -> {

                context.request().response().end();

                LOGGER.info("remote response data transfer end");

            });

            clientResponse.exceptionHandler(e -> {

                LOGGER.info("e", e);

            });

        });

  2. 设置闲置超时时间和最大队列大小。如果不设置,也可能导致连接不释放。新进来请求没有连接可用,造成等待挂死。需要注意的是,闲置超时时间的单位是秒,和其他接口不同。如果不看文档,肯定就弄错了。 

vertx.createHttpClient(

            new HttpClientOptions().setSsl(false)

                    .setVerifyHost(false)

                    .setTrustAll(true)

                    .setKeepAlive(true)

                    .setConnectTimeout(2000)

                    .setIdleTimeout(10)// 闲置超时时间

                    .setMaxWaitQueueSize(10)); //最大队列大小

3. 设置exceptionHandler。request和response都需要设置合理的异常处理,以跟踪错误。

        clietRequest.exceptionHandler(e -> {

            LOGGER.error("xxxxx", e);

            context.response().end();

        });

        clietRequest.connectionHandler(h -> {

            h.exceptionHandler(eh -> {

                LOGGER.error("conn", eh);

            });

            LOGGER.info("connection  " + h);

        });

 

 

在上述代码中,还有个坑

  context.request().response().headers().setAll(clientResponse.headers());

将一个请求的响应头全部拷贝到另外一个响应的头中(看起来是纯粹的HTTP转发)。这个操作是不对的。因为有些响应头是HTTP的控制消息,比如:Content-Length, Transfer-Encoding。一旦将两个头拷贝进去,就可能影响到HTTP报文的完整性(丢失或者多出额外的字节)。代码需要做一些特殊处理,不要拷贝这两个头。 

  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值