05 | HTTP调用:你考虑到超时、重试、并发了吗?

HTTP调用:你考虑到超时、重试、并发了吗?

进行 HTTP 调用本质上是通过 HTTP 协议进行一次网络请求,需要考虑以下三点

  1. 框架设置的默认超时是否合理;
  2. 考虑到网络的不稳定,超时后的请求重试是一个不错的选择,但需要考虑服务端接口的幂等性设计是否允许我们重试;
  3. 需要考虑框架是否会像浏览器那样限制并发连接数,以免在服务并发很大的情况下,HTTP 调用的并发数限制成为瓶颈。
配置连接超时和读取超时参数的学问

连接超时参数 ConnectTimeout,让用户配置建连阶段的最长等待时间;
读取超时参数 ReadTimeout,用来控制从 Socket 上读取数据的最长等待时间。

连接超时参数和连接超时的误区有这么两个
连接超时配置得特别长,比如 60 秒。三次握手这些是毫秒级的,如果几秒连接不上,那么基本就连接不上了,可以看看是不是防火墙的问题。
排查连接超时问题,却没理清连的是哪里。通常我们的服务会有多个节点,如果别的客户端通过客户端负载均衡技术来连接服务端,那么客户端和服务端会直接建立连接,此时出现连接超时大概率是服务端的问题;而如果服务端通过类似 Nginx 的反向代理来负载均衡,客户端连接的其实是 Nginx,而不是服务端,此时出现连接超时应该排查 Nginx。

读取超时参数和读取超时误区
第一个误区:认为出现了读取超时,服务端的执行就会中断。类似 Tomcat 的 Web 服务器都是把服务端请求提交到线程池处理的,只要服务端收到了请求,网络层面的超时和断开便不会影响服务端的执行
第二个误区:认为读取超时只是 Socket 网络层面的概念,是数据传输的最长耗时,故将其配置得非常短。比如 100 毫秒。
其实,发生了读取超时,网络层面无法区分是服务端没有把数据返回给客户端,还是数据在网络上耗时较久或丢包。
读取超时是服务处理超时,指的是,向 Socket 写入数据后,我们等到 Socket 返回数据的超时时间,其中包含的时间或者说绝大部分的时间,是服务端处理业务逻辑的时间。
第三个误区:认为超时时间越长任务接口成功率就越高,将读取超时参数配置得太长。
同步调用。如果超时时间很长,在等待服务端返回数据的同时,客户端线程(通常是 Tomcat 线程)也在等待,当下游服务出现大量超时的时候,程序可能也会受到拖累创建大量线程,最终崩溃。面向用户响应的请求或是微服务短平快的同步接口调用,并发量一般较大,我们应该设置一个较短的读取超时时间,以防止被下游服务拖慢,通常不会设置超过 30 秒的读取超时。

Feign 和 Ribbon 配合使用,你知道怎么配置超时吗?
  1. 默认情况下 Feign 的读取超时是 1 秒,如此短的读取超时算是坑点一。

如果要修改 Feign 客户端默认的两个全局超时时间,你可以设置feign.client.config.default.readTimeout 和feign.client.config.default.connectTimeout 参数:
feign.client.config.default.readTimeout=3000
feign.client.config.default.connectTimeout=3000

  1. 如果要配置 Feign 的读取超时,就必须同时配置连接超时,才能生效
  2. 单独的超时可以覆盖全局超时
  3. 除了可以配置 Feign,也可以配置 Ribbon 组件的参数来修改两个超时时间。这里的坑点三是,参数首字母要大写,和 Feign 的配置不同

ribbon.ReadTimeout=4000
ribbon.ConnectTimeout=4000

  1. 同时配置 Feign 和 Ribbon 的超时,以 Feign 为准
Ribbon 会自动重试请求

翻看 Ribbon 的源码可以发现,MaxAutoRetriesNextServer 参数默认为 1,也就是 Get请求在某个服务端节点出现问题(比如读取超时)时,Ribbon 会自动重试一次
解决方法

  1. 把发短信接口从 Get 改为 Post。这里的一个误区是,Get 请求的参数包含在 Url QueryString中,会受浏览器长度限制,所以一些同学会选择使用 JSON 以 Post 提交大参数,使用Get 提交小参数。
  2. 将 MaxAutoRetriesNextServer 参数配置为 0,禁用服务调用失败后在下一个服务端节点的自动重试。在配置文件中添加一行即可:ribbon.MaxAutoRetriesNextServer=0
并发限制了爬虫的抓取能力

案例:爬虫的效率很低。按理还说,爬一次需要1秒,那么我并发10个线程爬,也是耗时1秒。
查看 PoolingHttpClientConnectionManager 源码,可以注意到有两个重要参数:
defaultMaxPerRoute=2,也就是同一个主机 / 域名的最大并发请求数为 2。我们的爬虫需要 10 个并发,显然是默认值太小限制了爬虫的效率
maxTotal=20,也就是所有主机整体最大并发为 20,这也是 HttpClient 整体的并发度。举一个例子,使用同一
个 HttpClient 访问 10 个域名,defaultMaxPerRoute 设置为 10,为确保每一个域名都能达到 10 并发,需要把 maxTotal 设置为 100。
声明一个新的 HttpClient 放开相关限制,设置maxPerRoute 为 50、maxTotal 为 100。
httpClient2 = HttpClients.custom().setMaxConnPerRoute(10).setMaxConnTotal(20).build();

为什么很少见到写入超时,客户端发送数据到服务端,首先接力连接(TCP),然后写入TCP缓冲区,TCP缓冲区根据时间窗口,发送数据到服务端,因此写入操作可以任务是自己本地的操作,本地操作是不需要什么超时时间的,如果真的有什么异常,那也是连接(TCP)不上,或者超时的问题,连接超时和读取超时就能覆盖这种场景
Spring Boot 带来了【约定大于配置】的说法,但是,本文告诉我们,越是约定大于配置,越是要对那些“默认配置”心里有数才行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
`setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint)` 是一个 Qt 函数调用,用于将窗口设置为工具提示窗口,并且始终保持在顶部,并且窗口没有边框。这个函数可以在创建窗口时调用,也可以在运行时调用。 下面是一个使用 `setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint)` 的例子。在这个例子中,我们创建了一个简单的窗口,并将其设置为工具提示窗口、始终在顶部,并且没有边框: ```cpp #include <QtWidgets> int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; window.setGeometry(100, 100, 200, 200); window.setWindowTitle("Tool Window"); window.show(); // Set the window to be a tool window, always on top, and frameless window.setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint); return app.exec(); } ``` 在上面的例子中,我们创建了一个名为 `window` 的 `QWidget` 对象,并通过 `setGeometry` 函数设置了窗口的位置和大小。随后,我们将窗口的标题设置为 `"Tool Window"`,并将其显示出来。最后,我们调用 `setWindowFlags` 函数,并将其参数设置为 `Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint`,以将窗口设置为工具提示窗口、始终在顶部,并且没有边框。 需要注意的是,如果您想取消窗口的 `Tool`、`WindowStaysOnTopHint`、`FramelessWindowHint` 标志位,可以使用 `clearMask(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint)` 函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值