Vert.x HttpClient调用后端服务时使用Idle Timeout和KeepAlive Timeout的行为分析

其实网上有大量讨论HTTP长连接的文章,而且Idle Timeout和KeepAlive Timeout都是HTTP协议上的事情,跟Vert.x本身没有太大关系,只不过最近在项目上遇到了一些问题,用到了Vert.x的HttpClient,就干脆总结一下,留给自己今后做参考。

在使用Vert.x的HttpClient的时候,可以使用HttpClientOptions配置KeepAlive Timeout以及Idle Timeout的行为,本文将讨论在Vert.x HttpClient中Idle Timeout的设置、如何启用和禁用KeepAlive,以及如果启用KeepAlive,其超时设置(Timeout)对HTTP连接保活的影响。

需要注意的是,这是客户端的设置,服务端由于实现技术多样,这里不深入讨论,本文默认服务端已经开启了KeepAlive(事实上也是大多数HTTP服务器的默认行为)。

本文讨论的场景仅适用HTTP/1.1的情况,HTTP/1.0处理KeepAlive方式略有不同,HTTP/1.1默认支持KeepAlive,HTTP/1.0需要显式在header里加入Connection: keep-alive。

场景演练

这里我们设定多个场景来测试不同情况下,整个系统的行为表现是什么。

场景一:HttpClient禁用 KeepAlive

HttpClientOptions里使用setKeepAlive(false)来禁用KeepAlive:

 
final HttpClientOptions options = new HttpClientOptions()
.setKeepAlive(false);

此时,Vert.x Http Client会在请求头中加入connection: close,表示在完成一次HTTP request/response的流程后,服务端需要主动发起关闭连接请求:

Wireshark抓包分析:

  1. Vert.x HttpClient使用60489端口与服务端建立连接(SYN),服务端以(SYN, ACK)数据包回应,同意建立连接
  2. Vert.x HttpClient向服务端发送HTTP请求,服务端处理请求并返回
  3. 由于Vert.x HttpClient在发出HTTP请求时,使用了connection: close,所以服务端主动发起(FIN, ACK)数据包,表示服务端已关闭连接,客户端获得数据包后,返回ACK表示确认,然后也向服务端发出(FIN, ACK),表示客户端也关闭了连接,最后服务端返回ACK,表示确认

场景二:HttpClient启用KeepAlive

HttpClientOptions里使用setKeepAlive(false)来禁用KeepAlive:

 
final HttpClientOptions options = new HttpClientOptions()
.setKeepAliveTimeout(15)
.setKeepAlive(true);

 此时,Vert.x Http Client并不会发送connection: close头,因为HTTP/1.1默认使用长连接,所以无需额外指定任何请求头。在KeepAlive超时后,会由客户端主动关闭HTTP连接。

Wireshark抓包分析:

  1. Vert.x HttpClient使用60937端口与服务端建立连接(SYN),服务端以(SYN, ACK)数据包回应,同意建立连接
  2. Vert.x HttpClient向服务端发送HTTP请求,服务端处理请求并返回
  3. Vert.x HttpClient在等待了大约15秒以后(上面代码中setKeepAliveTimeout设置的15秒),由于没有新的HTTP请求需要占用连接,于是就向服务端发起(FIN, ACK)数据包,表示客户端已关闭连接,服务端获得数据包后,返回ACK表示确认,然后也向客户端发出(FIN, ACK),表示服务端也关闭了连接,最后客户端返回ACK,表示确认

如果服务端的KeepAlive Timeout大于HttpClient的KeepAlive Timeout,那么当一段时间内没有任何HTTP请求发出,在HttpClient KeepAlive首先超时前,HTTP连接可以一直被重用,直到HttpClient KeepAlive超时,由客户端发起关闭连接请求:

  1. 可以看到,客户端端口63094的连接在多次HTTP请求中一直被重用
  2. 15秒内,没有新的HTTP请求,客户端主动发起断开连接数据包

如果服务端的KeepAlive Timeout小于HttpClient的KeepAlive Timeout(比如服务端KeepAlive Timeout为10s),那么当一段时间内没有任何HTTP请求发出,服务端会首先发起关闭连接请求:

  1. Vert.x HttpClient使用64282端口与服务端建立连接(SYN),服务端以(SYN, ACK)数据包回应,同意建立连接
  2. 在多次HTTP请求过程中,HTTP连接被重用
  3. 10秒过后,服务端首先发起关闭连接请求
  4. 之后客户端再次发出HTTP请求,会重新新建一个HTTP连接

场景三:HttpClient同时使用Idle Timeout和KeepAlive Timeout

为了模拟这样的场景,在创建Vert.x HttpClient时,使用如下HttpClientOptions

 
final HttpClientOptions options = new HttpClientOptions()
.setIdleTimeout(5)
.setIdleTimeoutUnit(TimeUnit.SECONDS)
.setKeepAliveTimeout(20)
.setKeepAlive(true);

然后让服务端在返回HTTP Response的时候,先等待7秒钟:

 
[HttpGet(Name = "GetWeatherForecast")]
public async Task<IEnumerable<WeatherForecast>> Get()
{
await Task.Delay(7000);
return Enumerable.Range(1, 5).Select(index => new WeatherForecast
{
Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
TemperatureC = Random.Shared.Next(-20, 55),
Summary = Summaries[Random.Shared.Next(Summaries.Length)]
})
.ToArray();
}

Wireshark抓包分析:

  1. 建立连接
  2. 发送请求,服务器开始处理请求,需要7秒才能处理完
  3. 5秒后,客户端Idle Timeout了,等不起,就向服务端发起关闭连接,服务端响应关闭连接
  4. 下一次请求,需建立新的连接

因此,可以这样理解这两个设置:

  • 短的 Idle Timeout 和长的 KeepAlive Timeout: 如果 IdleTimeout 设置得比较短,而 KeepAliveTimeout 设置得比较长,连接会因为空闲超时(Idle Timeout)而关闭。因此,当新的 HTTP 请求到来时,需要建立新的连接。
  • 长的 Idle Timeout 和短的 KeepAlive Timeout: 如果 IdleTimeout 设置得比较长,而 KeepAliveTimeout 设置得比较短,在 Keep-Alive 有效时间内,即使当前连接上有请求在等待响应,该连接仍然可以接收新的 HTTP 请求,直到 Keep-Alive 超时触发。
  • 如果某个HTTP请求在某个HTTP连接上等待服务端返回,那么这个HTTP连接仍然处于活跃状态,此时并不会触发KeepAlive的倒计时

在vert.x中,RequestOptions也有类似的setIdleTimeout的方法来设置Idle Timeout,但它的作用域仅限于当前的HTTP请求,而HttpClientOptions.setIdleTimeout作用域为整个应用程序全局。

场景四:在服务端KeepAlive即将到期的时候发送HTTP请求

仍然使用上面【场景二】的环境设定,只是让客户端每隔KeepAlive Timeout相同时间发送一次请求,会发现,多数情况下,请求可以成功,但有时候会发生错误。比如,如果服务端KeepAlive Timeout为10秒,客户端也是每隔10秒发送请求:

  1. 建立连接,并发送HTTP请求,服务端正常响应
  2. 10秒后,客户端再次发出请求,服务端ACK了请求,但与此同时,服务端KeepAlive超时,于是就向客户端发送(RST, ACK)数据包用于复位连接(异常关闭连接),此时客户端就会报错:io.vertx.core.net.impl.ConnectionBase SEVERE: Connection reset

总结

  1. 一个HTTP连接是否能够重用,同时取决于客户端和服务端的KeepAlive行为
  2. 服务端通常是默认开启KeepAlive的,它也有一个默认值(不同服务端实现不一样)
  3. 客户端可以选择是否启用HTTP连接重用(启用或者禁用KeepAlive)
    1. 在HTTP/1.0中,启用时需要在Request Header中加入Connection: keep-alive,默认禁用
    2. 在HTTP/1.1中,禁用时,需要在Request Header中加入Connection: close,默认启用
  4. 如果客户端禁用,则HTTP连接不会重用,每次请求都会创建新的HTTP连接
  5. 如果客户端启用,并且客户端KeepAlive Timeout(ckt)小于服务端KeepAlive Timeout(skt),那么在min(ckt, skt)时间段内如果没有新的HTTP请求,并且HTTP连接处于空闲状态,客户端会发起HTTP连接关闭
  6. 如果客户端启用,并且客户端KeepAlive Timeout(ckt)大于服务端KeepAlive Timeout(skt),那么在min(ckt, skt)时间段内如果没有新的HTTP请求,并且HTTP连接处于空闲状态,服务端会发起HTTP连接关闭
  7. 当一个HTTP请求发送到服务端后,服务端需要一定时间处理,Vert.x HTTP Client设置Idle Timeout,可以使得当服务端在一定时间内没有响应时,客户端可以主动关闭HTTP连接。在客户端由于Idle Timeout而关闭连接之前,该HTTP请求仍在等待服务端的返回,此时承载该HTTP请求的HTTP连接仍可继续接受其它的HTTP请求
  8. 当服务端需要一定时间处理HTTP请求时,如果这个处理时间恰好与服务端KeepAlive Timeout相当,是有可能出现HTTP连接被异常关闭导致客户端报错的情况的。常见解决办法:
    1. 尽量避免在服务端KeepAlive超时时发出请求(根据实际情况调整KeepAlive参数或者定制HTTP请求发起策略)
    2. 重试机制
    3. 确保客户端和服务端超时设置合理,根据实际情况进行调整

KeepAlive Timeout和Idle Timeout的关系

两者是独立的设置,但在某些情况下可能会产生交互。例如,如果 IdleTimeout 设置的时间比 KeepAliveTimeout 短,那么连接可能会因为空闲超时而关闭,即使 Keep-Alive 允许更长时间的连接复用。

最佳实践(参考自ChatGPT)

  • 根据应用需求调整:
    • 如果应用程序需要频繁复用连接,可以设置较长的 KeepAliveTimeout
    • 如果需要防止连接长时间空闲占用资源,可以设置较短的 IdleTimeout
  • 平衡性能和资源:
    • 设置 IdleTimeout 时,确保它足够长以完成请求处理,但不要过长以免浪费资源。
    • 设置 KeepAliveTimeout 时,确保它能够有效地复用连接以提高性能。
  • 测试和监控:
    • 在实际应用中,监控连接的使用情况,并根据性能和资源使用情况调整这些超时设置。

通过合理设置这两个超时值,可以优化连接的使用效率,同时避免不必要的资源占用。

外包干了三年,快要废了。。。-CSDN博客  https://blog.csdn.net/HUA6911/article/details/142107404?spm=1000.2115.3001.6382&utm_medium=distribute.pc_feed_v2.none-task-blog-hot-4-142107404-null-null.329^v9^%E4%B8%AA%E6%8E%A8pc%E9%A6%96%E9%A1%B5%E6%8E%A8%E8%8D%90%E2%80%94%E6%A1%B66&depth_1-utm_source=distribute.pc_feed_v2.none-task-blog-hot-4-142107404-null-null.329^v9^%E4%B8%AA%E6%8E%A8pc%E9%A6%96%E9%A1%B5%E6%8E%A8%E8%8D%90%E2%80%94%E6%A1%B66

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/879485.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Codes 开源研发项目管理平台——敏捷测试管理创新解决方案

前言 Codes 是国内首款重新定义 SaaS 模式的开源项目管理平台&#xff0c;支持云端认证、本地部署、全部功能开放&#xff0c;并且对30人以下团队免费。它通过整合迭代、看板、度量和自动化等功能&#xff0c;简化测试协同工作&#xff0c;使敏捷测试更易于实施。并提供低成本的…

计算机人工智能前沿进展-大语言模型方向-2024-09-13

计算机人工智能前沿进展-大语言模型方向-2024-09-13 1. OneEdit: A Neural-Symbolic Collaboratively Knowledge Editing System Authors: Ningyu Zhang, Zekun Xi, Yujie Luo, Peng Wang, Bozhong Tian, Yunzhi Yao, Jintian Zhang, Shumin Deng, Mengshu Sun, Lei Liang, Z…

【AI学习笔记】初学机器学习西瓜书概要记录(二)常用的机器学习方法篇

初学机器学习西瓜书的概要记录&#xff08;一&#xff09;机器学习基础知识篇(已完结) 初学机器学习西瓜书的概要记录&#xff08;二&#xff09;常用的机器学习方法篇(持续更新) 初学机器学习西瓜书的概要记录&#xff08;三&#xff09;进阶知识篇(待更) 文字公式撰写不易&am…

设计模式 享元模式(Flyweight Pattern)

享元模式 简绍 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构型设计模式&#xff0c;它的目的是通过共享技术来有效地支持大量细粒度的对象。享元模式可以极大地减少内存的使用&#xff0c;从而提高程序的性能。它特别适用于需要创建大量相似对象的场景&#…

基于web的工作管理系统设计与实现

博主介绍&#xff1a;专注于Java vue .net php phython 小程序 等诸多技术领域和毕业项目实战、企业信息化系统建设&#xff0c;从业十五余年开发设计教学工作 ☆☆☆ 精彩专栏推荐订阅☆☆☆☆☆不然下次找不到哟 我的博客空间发布了1000毕设题目 方便大家学习使用 感兴趣的…

嵌入式-QT学习-小练习

1. 实现多窗口 2. 给按键增加图标 3. 动图展示 结果演示&#xff1a; Mul_Con main.cpp #include "widget.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }一、第一个窗口展示 …

C++ -命名空间-详解

博客主页&#xff1a;【夜泉_ly】 本文专栏&#xff1a;【C】 欢迎点赞&#x1f44d;收藏⭐关注❤️ C -命名空间-详解 1.C语言缺点之一 -- 命名冲突2.命名空间2.1定义2.2使用访问命名空间中的变量展开命名空间域指定访问命名空间域 2.3其他功能 3.C 标准库中的命名空间指定展开…

【网络安全】一篇文章带你了解CTF那些事儿

&#x1f91f; 基于入门网络安全/黑客打造的&#xff1a;&#x1f449;黑客&网络安全入门&进阶学习资源包 一、什么是CTF&#xff1f; CTF&#xff0c;即 Capture The Flag&#xff0c;中文名为夺旗赛&#xff0c;是一种网络安全技术人员之间进行技术竞技的比赛形式。…

保护您的隐私:隐藏 IP 地址的重要性

在当今的数字时代&#xff0c;我们的在线隐私和安全变得比以往任何时候都更加重要。浏览互联网时保护自己的一种方法是隐藏您的 IP 地址。 但是为什么要隐藏您的 IP 地址以及如何有效地做到这一点&#xff1f; 隐藏您的 IP 地址有助于保护您的在线匿名性。您的 IP 地址就像您的…

高速数据转换器设计(一):简介

【注&#xff1a;本文基于《高速数据转换器设计》一书进行学习、总结编撰&#xff0c;适合新手小白进行学习】 目录 1.1 理想数据转换器 1.2 采样操作 1.2.1 冲激采样 1.2.2 采样-保持(S-H) 1.2.3 跟踪-保持 1.2.4 带通采样定理 1.3 信号重构 1.4 量化 1.4.1 量化器 …

SEO 和内容营销:吸引更多人阅读你下一篇文章的3个步骤

SEO和内容营销之间的界限模糊不清。它们显然不同&#xff0c;但很难确切指明其中的界限。 想一想&#xff1a;昼夜的差别是明显的&#xff0c;像白天和黑夜。 但对于昼夜交替的那一刻——究竟是什么时候呢&#xff1f; 你可能认为是在日落时分。但这忽略了市民黄昏&#xff…

【CSS in Depth 2 精译_033】5.4 Grid 网格布局的显示网格与隐式网格(中)

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第一章 层叠、优先级与继承&#xff08;已完结&#xff09; 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位&#xff08;已完结&#xff09; 2.1 相对…

影刀RPA实战:网页爬虫之携程酒店数据

1.实战目标 大家对于携程并不陌生&#xff0c;我们出行定机票&#xff0c;住酒店&#xff0c;去旅游胜地游玩&#xff0c;都离不开这样一个综合性的网站为我们提供信息&#xff0c;同时&#xff0c;如果你也是做旅游的公司&#xff0c;那携程就是一个业界竞争对手&#xff0c;…

后台数据管理系统 - 项目架构设计-Vue3+axios+Element-plus(0917)

七、引入 element-ui 组件库 我的Git仓库&#xff1a;https://gitee.com/msyycn/vue3-hei-ma.git 官方文档&#xff1a; https://element-plus.org/zh-CN/ 安装 $ pnpm add element-plus自动按需&#xff1a; 安装插件 pnpm add -D unplugin-vue-components unplugin-auto…

Python VS Golng 谁更胜一筹?

今天我们聊聊Python和Golang这俩到底谁更胜一筹。 这个话题我已经在各种技术论坛上看到无数次了&#xff0c;每次都能引起一波热烈的讨论。作为一个多年写代码的老程序员&#xff0c;今天就站在我的角度&#xff0c;和大家掰扯掰扯这两个语言各自的优缺点。 1. 性能与并发模型…

小程序渗透 | 利用ce修改器挖掘内存修改漏洞

CE修改器原理 ce修改器可以修改内存数值&#xff0c;因为有些程序会把一些值放在本地&#xff0c;然后改动的时候访问的本地的值&#xff0c;修改之后&#xff0c;客户端服务器再次发生交互的时候&#xff0c;把修改的值发出去&#xff0c;可能会影响到服务器的数据&#xff0…

【sgCreateCallAPIFunction】自定义小工具:敏捷开发→调用接口方法代码生成工具

<template><div :class"$options.name" class"sgDevTool"><sgHead /><div class"sg-container"><div class"sg-start"><div style"margin-bottom: 10px">调用接口方法定义列表</div…

五种数据库特性对比(Redis/Mysql/SQLite/ES/MongoDB)

做后端开发的程序员基本都要学会数据库的相关知识。 1、关系型数据 今天就着这段时间了解大模型的事需要牵扯到是我们接触最多的、也是入门后端必学的关系型数据库。在关系型数据库中&#xff0c;数据以表的形式进行组织和存储&#xff0c;每个表就像一个 Excel 表格&#xf…

superset 解决在 mac 电脑上发送 slack 通知的问题

参考文档: https://superset.apache.org/docs/configuration/alerts-reports/ 核心配置: FROM apache/superset:3.1.0USER rootRUN apt-get update && \apt-get install --no-install-recommends -y firefox-esrENV GECKODRIVER_VERSION0.29.0 RUN wget -q https://g…

Windows 常用的键盘快捷键总结

在日常工作或学习中&#xff0c;使用键盘快捷键不仅能够显著提高操作速度&#xff0c;还可以减少对鼠标的依赖&#xff0c;提升整体工作效率。Windows 操作系统为用户提供了众多功能强大的键盘快捷键&#xff0c;覆盖了不同方面&#xff0c;下面就给大家总结了常用的键盘快捷键…