当前位置: 首页 > news >正文

【nginx实战】通过nginx实现http 长连接(即keep alive)

文章目录

  • 一. http的长连接历史
    • 1. HTTP短连接模型
    • 2. HTTP长连接模型
  • 二. nginx作为代理时实现HTTP长连接
    • 1. nginx与client的长连接
      • 1.1. keepalive_timeout指令
      • 1.2. keepalive_requests指令
        • * 场景分析
    • 2. 保持和server的长连接
      • 2.1. location设置
        • * 场景分析
      • 2.2. upstream设置
        • * 场景分析
          • 场景1
          • 场景2
          • 场景3

长连接基础:先了解为什么要保持长连接,http的长连接历史。
长连接实战:接着如何分析如何通过nginx设置长连接。如果不恰当的设置长连接,会出现什么问题。

一. http的长连接历史

HTTP是属于应用层(七层)的协议,传输层(四层)使用的是TCP协议,所以HTTP的长连接和短连接,其本质就是TCP的长连接和短连接;
HTTP是一个无状态的面向连接的协议,指的是协议对于事务处理没有记忆能力,服务器不知道客户端是什么状态,但无状态不代表HTTP不能保持TCP连接;
TCP建立连接和断开连接是需要三握四挥的,也就说HTTP连接的建立与断开是消耗资源的。

接下来正式了解下http长短连接模型

1. HTTP短连接模型

短连接的基本逻辑与特点
HTTP 短连接模型是最早期的模型,也是 HTTP/1.0 的默认模型。在早期,HTTP 使用一个简单的模型来处理这样的连接。这些连接的生命周期是短暂的:每发起一个请求时都先有一次TCP握手,然后创建一个新连接,并在收到应答时立即关闭。

持续的短连接是耗时、耗费资源的
实际上,TCP 协议握手本身就是耗费时间的,所以 TCP 可以保持更多的热连接来适应负载。短连接破坏了 TCP 具备的能力,新的冷连接降低了其性能。

长短连接的设置

在 HTTP/1.0 中如果没有指定 Connection协议头,或者是值被设置为 close就会启用短连接模型,要在 HTTP/1.0 中启用长连接模型,需要在协议头中指定Connection: Keep-Alive ,不过并不建议这样操作。

而在 HTTP/1.1 中,默认使用长连接模型,只有当 Connection被设置为 close 时才会用到这个短连接模型,协议头都不用再去声明它(但是一般还是会把它加上,以防万一因为某种原因要退回到 HTTP/1.0 )。

 

2. HTTP长连接模型

长连接的趋势
后来,网页需要请求的资源越来越多,短连接模型显然已经十分吃力了。因为短连接有两个比较大的问题:创建新连接耗费的时间尤为明显(三次握手很耗费时间),另外 TCP 连接的性能只有在该连接被使用一段时间后(热连接)才能得到改善。因此在HTTP/1.1中引入了长连接模型。

在 HTTP/1.1 之前,长连接也被称为keep-alive 连接。
一个长连接会保持一段时间,重复用于发送一系列请求,节省了新建 TCP 连接握手的时间,还可以利用 TCP 的性能增强能力(ing)。当然这个连接也不会一直保留着:连接在空闲一段时间后会被关闭(服务器可以使用 Keep-Alive 协议头来指定一个最小的连接保持时间)。

长连接的缺点:资源占用问题
使用长连接本质上是因为当不断地三次握手建立连接所消耗的资源大于维持连接所需要的资源

当处于空闲状态时,它还是会消耗服务器资源。如果空闲较长,可以使用非长连接,即尽快关闭那些空闲的连接,也能对性能有所提升。

二. nginx作为代理时实现HTTP长连接

当我们配置Nginx作为代理服务器的时候,想要支持HTTP长连接,需要client到Nginx和Nginx到server(nginx中upstream配置的server)都是长连接,因为此时Nginx既是client的server也是server的client。

多个HTTP请求通过复用TCP连接,会达到以下效果:

  1. 减少握手次数
  2. 通过减少并发连接数减少了服务器资源的消耗
  3. 降低TCP拥塞控制的影响

 

1. nginx与client的长连接

为了在client和nginx之间保持长连接,有两个要求:

  1. client发送的HTTP请求要求keep alive
    2.nginx设置上支持keep alive:默认情况下,nginx已经自动开启了对client连接的keep alive支持。

 

1.1. keepalive_timeout指令

语法:用户一个HTTP请求连接完成以后,最多经过timeout时间,如果还是没有新的请求,就会关闭连接

Syntax:    keepalive_timeout timeout [header_timeout];
Default:   keepalive_timeout 75s;
Context:   http, server, location1. 第一个参数设置keep-alive客户端连接在服务器端保持开启的超时值。值为0会禁用keep-alive客户端连接。默认75s一般情况下也够用,对于一些请求比较大的内部服务器通讯的场景,适当加大为120s或者300s。2. (可选的)第二个参数在响应的header域中设置一个值“Keep-Alive: timeout=time”。第二个参数通常可以不用设置。

 

1.2. keepalive_requests指令

使用语法:

Syntax:	keepalive_requests number;
Default:	keepalive_requests 1000;
Context:	http, server, location;该指令首次出现在版本0.8.0中。在版本1.19.10之前,默认值为1001.参数的作用
>一个TCP(keep-alive)连接上最多执行多少个HTTP请求。
>当达到这个参数设置的最大值(默认是1000)时,则nginx会强行关闭这个长连接,
>逼迫客户端不得不重新建立新的长连接。注意:
定期关闭连接是为了释放每个连接的内存分配。
因此,设置过高的最大请求数可能导致过多的内存使用,这是不推荐的。

 

* 场景分析

这个参数往往被大多数人忽略,因为大多数情况下当QPS(每秒请求数)不是很高时,默认值100凑合够用。但是,对于一些QPS比较高(比如超过10万QPS,甚至达到30万,50万甚至更高) 的场景,默认的1000就不适用了。因为此时会频繁创建长连接。

出现频繁的关闭、创建连接:

当QPS=10万/s时,客户端每秒发送10万个请求(通常建立有多个长连接),每个连接只能最多跑1000次请求,意味着平均每秒钟就会有100个长连接因此被nginx关闭。同样意味着为了保持QPS,客户端不得不每秒中重新新建100个连接。

大量的TIME_WAIT

如果用netstat命令看客户端机器,就会发现有大量的TIME_WAIT的socket连接(即使此时keep alive已经在client和nginx之间生效)。因此对于QPS较高的场景,非常有必要加大这个参数,以避免出现大量连接被生成再抛弃的情况,减少TIME_WAIT。

 

2. 保持和server的长连接

2.1. location设置

为了让nginx和server(upstream块中的servers)之间保持长连接,典型设置如下:

http {upstream  BACKEND {server   192.168.0.18080  weight=1 max_fails=2 fail_timeout=30s;server   192.168.0.28080  weight=1 max_fails=2 fail_timeout=30s;keepalive 300;        // 这个很重要!}server {listen 8080 default_server;server_name "";location /  {proxy_pass http://BACKEND;proxy_set_header Host  $Host;proxy_set_header x-forwarded-for $remote_addr;proxy_set_header X-Real-IP $remote_addr;add_header Cache-Control no-store;add_header Pragma  no-cache;proxy_http_version 1.1;                    // 这两个最好也设置proxy_set_header Connection "";client_max_body_size  3072k;client_body_buffer_size 128k;}}
}

location中的两个参数:

  proxy_http_version 1.1;                   proxy_set_header Connection "";
  1. HTTP协议中对长连接的支持是从1.1版本之后才有的,因此最好通proxy_http_version指令设置为"1.1";
  2. 代表来自client的请求Connection header会被清理。清理 Connection 头可以确保代理层完全控制连接的生命周期。

 

* 场景分析

假设client和nginx之间是短连接,nginx和upstream之间可以开启长连接。这种情况下必须清理来自client请求中的Connection header,如果不清理,则会将client的header传递过来导致不能开启长连接。

 

2.2. upstream设置

upstream设置中,有个参数要特别的小心,就是这个keepalive。

nginx keepalive语法:

Syntax:   keepalive connections;
Default:  —
Context:  upstream

keepalive参数作用

connections参数设置每个worker进程与upstream server建立的最多空闲 的keepalive连接数量。当这个数量被突破时,最近使用最少的连接将被关闭。

特别提醒:keepalive指令不会限制一个nginx worker进程到upstream服务器连接的总数量。connections参数应该设置为一个足够小的数字来让upstream服务器来处理新进来的连接。

 

* 场景分析

场景描述

有一个HTTP服务,作为upstream server接收请求,响应时间为100毫秒(一秒能处理10个请求)。如果要达到10000 QPS的性能,就需要在nginx和upstream服务器之间建立大约1000条HTTP连接。
nginx为此建立连接池,然后请求过来时为每个请求分配一个连接,请求结束时回收连接放入连接池中,连接的状态也就更改为idle。

我们再假设这个upstream服务器的keepalive参数设置比较小,比如常见的10.
 

场景1

假设请求和响应是均匀而平稳的,那么这1000条连接应该都是一放回连接池就立即被后续请求申请使用,线程池中的idle线程会非常的少,趋进于零。
我们以100毫秒为一个单位,来看连接的情况:

  • 每100毫秒有100个新请求,需要100个连接;根据前面假设可以知道每100毫秒有100个请求结束,可以释放100个连接
  • 如果请求和应答都均匀,则100毫秒内释放的连接刚好够用,不需要新建连接,连接池也不空闲。
场景2

回到现实世界,请求通常不是足够的均匀和平稳,为了简化问题,我们假设应答始终都是平稳的,只是请求不平稳:

  1. 假设此时100毫秒内只有50个请求。此时连接池内有50个空闲连接。注意看keepalive=10的设置,这意味着连接池中最多容许保留有10个空闲连接。因此nginx不得不将这50个空闲连接中的40个关闭,只留下10个。
  2. 再下一个100个毫秒,有150个请求进来,有100个请求结束任务释放连接。150 - 100 = 50,空缺了50个连接,减掉前面连接池保留的10个空闲连接,nginx不得不新建40个新连接来满足要求。
    我们可以看到,在短短的200毫秒内,仅仅因为请求不够均匀,就导致nginx在前100毫秒判断空闲连接过多关闭了40个连接,而后10毫秒又不得不新建40个连接来弥补连接的不足。
场景3

假设请求是均匀的,而应答不再均匀,前100毫秒只有50个请求结束,后100毫秒有150个:

  1. 前100毫秒,进来100个请求,只结束了50个请求,导致此时连接不够下次请求用,nginx为此新建50个连接,此时有150个连接;
  2. 后100毫秒,进来100个请求,结束150个请求,导致空闲连接过多,ngixn为此关闭了150-10=140个空闲连接。

 

小结

现实世界中请求往往不均匀,服务器处理请求的时间也不平稳,当qps很高时,就会在短时间内导致两种非常矛盾现象: 1. 连接不够用,造成新建连接;2. 连接空闲,造成关闭连接。从而使得总连接数出现反复震荡,不断的创建新连接和关闭连接,使得长连接的效果被大大削弱。

keepalive参数设置方法:比如前面10000 QPS和100毫秒响应时间就可以推算出需要的长连接数量大概是1000. 然后将keepalive设置为这个长连接数量的10%到30%。

 

参考:
https://www.jianshu.com/p/142b35998947

相关文章:

【nginx实战】通过nginx实现http 长连接(即keep alive)

文章目录 一. http的长连接历史1. HTTP短连接模型2. HTTP长连接模型 二. nginx作为代理时实现HTTP长连接1. nginx与client的长连接1.1. keepalive_timeout指令1.2. keepalive_requests指令* 场景分析 2. 保持和server的长连接2.1. location设置* 场景分析 2.2. upstream设置* 场…...

通用函数

目录 处理null 多数值判断 Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 Oracle 提供了两个简单的数据处理函数: nvl()、decode()。在版本升级的过程中,这两个函数又衍生出了许多子函数 处理null 下面首先…...

Linux 查看系统信息 + 服务信息命令(简记)

概述 作用:Linux 运维工作中常用的命令速查 小步教程 (xiaobuteach.com) Linux 命令大全 | 菜鸟教程 (runoob.com) 文本编辑器vim 本章大纲 | 小步教程 vim 多文件编辑 | 小步教程 常用 ps 查看服务启动命令 Linux ps 命令 | 菜鸟教程 (runoob.com) # 查找…...

有了Future为什么还要CompletableFuture?

文章目录 Future 接口理论知识复习Future 接口概述场景描述小结 Future 接口常用实现类 FutureTask 异步任务Future 的作用Futrue 编码测试优缺点分析优点缺点小结 面对一些复杂的任务对于简单的业务场景使用 Future 接口完全 OK回调通知创建异步任务多个任务前后依赖可以组合对…...

Android super.img解包和打包指南(含工具下载lpunpack、lpmake、lpdump)

本文所有命令均需要在linux 上执行 一、解包 1、将Android sparse image格式的super.img转成二进制文件 $ sudo apt install android-sdk-libsparse-utils $ simg2img super.img super.img.bin 2、下载工具lpunpack 和lpmake、lpdump 以及其依赖库 下载地址:https://downl…...

端到端实现高精地图重建(TopoNet解读和横评)

论文出处 [2304.05277] Graph-based Topology Reasoning for Driving Scenes (arxiv.org)https://arxiv.org/abs/2304.05277 TopoNet TopoNet的目标是从车辆上安装的多视角摄像头获取图像,感知实体并推理出驾驶场景的拓扑关系,实现端到端预测&#xf…...

系统架构20 - 统一建模语言UML(上)

统一建模语言 组成要素事物关系 在目前的软件开发方法中,面向对象的方法占据着主导地位。面向对象方法的主导地位也决定着软件开发过程模型化技术的发展,面向对象的建模技术方法也就成为主导的方法。 公认的面向对象建模语言出现于20世纪70年代中期。从1…...

数据库学习笔记2024/2/4

随笔 1. 为什么学? 认识数据,熟悉数据,掌握数据。 进企业必备技能。 2. 怎么学? 1、MySQL数据库就是存储和管理数据的一个大型软件,这个软件有一个专门的语言叫SQL,主要学的是SQL语言,但想要达到企业用人标准,就还得学会熟练使用MySQL这个软件。 2、学习分三阶段: 一. …...

Apache POI 处理excel文件 记录用法

Apache POI 写excel public static void write() throws IOException {//再内存中创建了一个Excel文件XSSFWorkbook excel new XSSFWorkbook();//创建一个sheet页XSSFSheet sheet excel.createSheet("info");//这里创建行对象,这里的rownum 是从0开始的,类似于数…...

Transformer实战-系列教程2:Transformer算法解读2

🚩🚩🚩Transformer实战-系列教程总目录 有任何问题欢迎在下面留言 Transformer实战-系列教程1:Transformer算法解读1 Transformer实战-系列教程2:Transformer算法解读2 5、Multi-head机制 在4中我们的输入是X&#x…...

python_蓝桥杯刷题记录_笔记_全AC代码_入门3

前言 记录我的解法以及笔记思路,谢谢观看。 题单目录 1.P2141 [NOIP2014 普及组] 珠心算测验 2.P1567 统计天数 3.P1055 [NOIP2008 普及组] ISBN 号码 4.P1200 [USACO1.1] 你的飞碟在这儿 Your Ride Is Here 5.P1308 [NOIP2011 普及组] 统计单词数 6.P1047 […...

STM32 IIC电量计LTC2944

1 描述 LTC2944 可在便携式产品应用中测量电池充电状态、电池电压、电池电流及其自身温度。宽输入电压范围允许使用高达 60V 的多节电池。精密库仑反向积分电流通过电池正极端子与负载或充电器之间的检测电阻器。 电压、电流和温度由内部 14 位无延迟 ΔΣ™ ADC 测量。测量结…...

Linux 链接 GitHub 出现 Connection timed out

问题 安装GIT并完成公钥验证:Linux 系统拉取 Github项目 [rootxxx devtools]# ssh -T gitgithub.com ssh: connect to host github.com port 22: Connection timed out解决方案 进入在存放公钥私钥id_rsa.pub文件里,新建/修改config文本 [rootxxx my…...

vulnhub靶场之Thales

一.环境搭建 1.靶场描述 Description : Open your eyes and change your perspective includes 2 flags:user.txt and root.txt. Telegram: machineboy141 (for any hint) This works better with VIrtualBox rathe than VMware 2.靶场地址 https://www.vulnhub.com/entry/t…...

Qt之使用Qt内置图标

一效果 二.原理 Qt内置图标封装在QStyle中,共七十多个图标,可以直接拿来用,能应付不少简单程序需求,不用自己去找图标并添加到资源文件了。 下面是内置图标的枚举定义: enum StandardPixmap {SP_TitleBarMenuButton,SP_TitleBarMinButton,SP_TitleBarMaxButton,SP_T…...

《计算机网络简易速速上手小册》第10章:未来网络技术趋势(2024 最新版)

文章目录 10.1 边缘计算与网络设计 - 未来网络的速度与激情10.1.1 基础知识10.1.2 重点案例:使用 Python 实现边缘计算的实时视频分析准备工作Python 脚本示例 10.1.3 拓展案例1:智能交通系统Python 脚本示例 - 边缘计算设备上的交通流量分析 10.1.4 拓展…...

Vue引入Axios

1.命令安装axios和vue-axios npm install axios --save npm install vue-axios --save 2.package.json查看版本 3.在main.js中引用 import axios from axios; import VueAxios from vue-axios; Vue.use(VueAxios,axios) 4.如何使用 (初始化方法) 将下列代…...

【git 本地管理版本及与github合并】 Init Push Pull操作解决方案

文章目录 创建本地仓库,并与远程仓库链接更新本地仓库并使用Push推送到远程仓库 1. 几种基础命令介绍:2. git push操作流程 .gitignore删除本地仓库,断开本地与远程的链接设置用于提交commit的用户名,邮箱,以便githu…...

JavaSE-项目小结-IP归属地查询(本地IP地址库)

一、项目介绍 1. 背景 IP地址是网络通信中的重要标识,通过分析IP地址的归属地信息,可以帮助我们了解访问来源、用户行为和网络安全等关键信息。例如应用于网站访问日志分析:通过分析访问日志中的IP地址,了解网站访问者的地理位置分…...

使用最大边界相关算法处理文章自动摘要

一、需求背景 对于博客或者文章来说,摘要是普遍性的需求。但是我们不可能让作者自己手动填写摘要或者直接暴力截取文章的部分段落作为摘要,这样既不符合逻辑又不具有代表性,那么,是否有相关的算法或者数学理论能够完成这个需求呢&…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码,CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短,所以CPU会不断地切换线程执行,从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机,它可以执行Java字节码。Java虚拟机是Java平台的一部分,Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

掌握 HTTP 请求:理解 cURL GET 语法

cURL 是一个强大的命令行工具,用于发送 HTTP 请求和与 Web 服务器交互。在 Web 开发和测试中,cURL 经常用于发送 GET 请求来获取服务器资源。本文将详细介绍 cURL GET 请求的语法和使用方法。 一、cURL 基本概念 cURL 是 "Client URL" 的缩写…...