Nginx配置WebSocket反向代理

1、WebSocket协议

​ WebSocket协议相比较于HTTP协议成功握手后可以多次进行通讯,直到连接被关闭。但是WebSocket中的握手和HTTP中的握手兼容,它使用HTTP中的Upgrade协议头将连接从HTTP升级到WebSocket。这使得WebSocket程序可以更容易的使用现已存在的基础设施。

2、Nginx配置WebSocket反向代理

$ vim /usr/local/nginx/conf/nginx.conf (nginx配置文件)

# 在http上下文中增加如下配置,确保Nginx能处理正常http请求。

http {
    
  # 根据请求头中的"Upgrade"字段来确定是否升级连接。如果请求头中的"Upgrade"字段的值为"default",则将其升级为"upgrade"。
    如果请求头中的"Upgrade"字段的值为空字符串(即没有"Upgrade"字段),则将连接关闭。
    对于其他情况,默认将"Upgrade"字段的值设为"upgrade"。
  map $http_upgrade $connection_upgrade {
    default upgrade;
    ''   close;
  }
    
  # 定义了一个名为"websocket"的负载均衡集群。
  upstream websocket {
    #ip_hash; # 这是一个负载均衡算法的注释,表示使用IP哈希算法进行负载均衡。
    server localhost:8010;  # 制定一个后端服务器地址
    server localhost:8011;
  }

  # 以下配置是在server上下文中添加,location指用于websocket连接的path。
  server {
    listen       80;
    server_name localhost;
    access_log /var/log/nginx/yourdomain.log;

    location / {
      proxy_pass http://websocket;
      proxy_http_version 1.1; # 指定使用HTTP/1.1协议进行代理
      proxy_set_header Upgrade $http_upgrade; # 将请求头中的"Upgrade"字段的值传递给后端服务器。
      proxy_set_header Connection $connection_upgrade; # 请求头中的"Connection"字段的值设为"upgrade",表示要升级连接。
	  proxy_connect_timeout 4s; # 设置与后端服务器建立连接的超时时间为4秒。
	  proxy_read_timeout 7200s; # 置从后端服务器读取响应的超时时间为7200秒。
	  proxy_send_timeout 12s; # 设置向后端服务器发送请求的超时时间为12秒。
	  proxy_set_header Host $host; # 将请求头中的"Host"字段的值设为当前请求的主机名。
      proxy_set_header X-Real-IP $remote_addr; # 将请求头中的"X-Real-IP"字段的值设为客户端的真实IP地址。
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 将请求头中的"X-Forwarded-For"字段的值设为客户端IP地址的列表,这样后端服务器就可以知道请求的真实来源IP。
	  proxy_set_header HTTP_X_FORWARDED_FOR $remote_addr; # 将请求头中的"HTTP_X_FORWARDED_FOR"字段的值设为客户端的真实IP地址。
	  proxy_set_header X-Forwarded-Proto $scheme; # 将请求头中的"X-Forwarded-Proto"字段的值设为请求的协议类型(HTTPHTTPS)。
	  proxy_redirect   default; # 默认启用代理重定向。
    }
  }
}

核心是下面的配置 其他和普通反向代理没区别, 表示请求服务器升级协议为WebSocket

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

这里面的关键部分在于HTTP的请求中多了如下头部:

Upgrade: websocket
Connection: Upgrade

这两个字段表示请求服务器升级协议为WebSocket。服务器处理完请求后,响应如下报文:

# 状态码为101
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: upgrade

​ 告诉客户端已成功切换协议,升级为Websocket协议。握手成功之后,服务器端和客户端便角色对等,就像普通的Socket一样,能够双向通信。不再进行HTTP的交互,而是开始WebSocket的数据帧协议实现数据交换。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XqnLRKLi-1690603346484)(E:\PRD\Images\image-20230729114740230.png)]

3、配置反向代理常见问题

3.1 为什么要配置Host参数?

WebSocket反向代理需要配置host参数的原因是WebSocket协议的特性。在WebSocket协议中,客户端在建立与服务端的WebSocket连接时,会发送一个Origin头部字段,用于标识请求的来源。这个Origin字段的值通常是客户端的域名。

当使用反向代理来代理WebSocket请求时,代理服务器会接收到客户端的WebSocket连接请求。如果没有配置host参数,代理服务器会将自己的主机名作为Origin字段的值发送给服务端。而服务端在验证WebSocket连接时会比较Origin字段的值与其预期的值是否一致,如果不一致,则会拒绝连接。

为了解决这个问题,需要在反向代理配置中明确指定host参数,将客户端的原始域名作为host参数的值发送给服务端。这样服务端就能正确验证WebSocket连接的来源,从而确保连接的安全性和正确性。

3.2 WebSocket反向代理为什么要设置http协议为1.1版本

当使用WebSocket反向代理时,将HTTP协议版本设置为1.1是为了确保与WebSocket协议的兼容性和正常工作。

WebSocket协议是在HTTP协议基础上进行升级的,它的握手过程与HTTP握手类似。在进行WebSocket握手时,客户端会发送一个类似HTTP请求的握手请求,然后服务器进行响应,最终建立WebSocket连接。在这个过程中,需要使用HTTP的一些特性和头部字段。

将HTTP协议版本设置为1.1是因为WebSocket握手过程使用了HTTP/1.1的一些新特性,包括Upgrade头部字段和Connection头部字段的值设置为Upgrade。当HTTP协议版本为1.1时,代理服务器能够正确理解并处理这些头部字段,从而正确地转发WebSocket握手请求和响应。

如果将HTTP协议版本设置为较低的版本,如HTTP/1.0,代理服务器可能无法正确处理WebSocket握手请求,导致握手失败或连接无法建立。因此,为了保证WebSocket反向代理的正常工作,一般会将HTTP协议版本设置为1.1版本。

需要注意的是,虽然WebSocket握手过程使用了HTTP协议,但WebSocket连接建立后,实际上是通过WebSocket协议进行数据传输的,而不是HTTP协议。所以,一旦建立了WebSocket连接,HTTP协议版本的设置对后续的数据传输没有影响。

感谢博主:https://blog.csdn.net/weixin_42083036/article/details/110133421

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

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

相关文章

微服务入门---SpringCloud(一)

微服务入门---SpringCloud(一) 1.认识微服务1.0.学习目标1.1.单体架构1.2.分布式架构1.3.微服务1.4.SpringCloud1.5.总结 2.服务拆分和远程调用2.1.服务拆分原则2.2.服务拆分示例2.2.1.导入Sql语句2.2.2.导入demo工程 2.3.实现远程调用案例2.3.1.案例需求…

【Koa】[NoSQL] Koa中相关介绍和使用Redis MongoDB增删改查

目录 NoSQL非关系型数据库关系型数据库(RMDB)介绍非关系型数据库(NoSQL)介绍Redis & MongoDB 在 Koa 中使用 Redis (了解)Redis 的安装和使用在 Koa 中连接 和 调用 Redis 在 Koa 中使用 MongoDBMongoDB 的安装MongoShell 操作…

【Spring框架】SpringBoot配置文件

目录 配置文件作用application.properties中午乱码问题:配置文件里面的配置类型分类SpringBoot热部署properties基本语法properties配置文件的优缺点:yml配置文件说明yml基本语法配置对象properties VS yml 配置文件作用 整个项⽬中所有重要的数据都是在…

SQL-每日一题【1068. 产品销售分析 I】

题目 销售表 Sales: 产品表 Product: 写一条SQL 查询语句获取 Sales 表中所有产品对应的 产品名称 product_name 以及该产品的所有 售卖年份 year 和 价格 price 。 查询结果中的顺序无特定要求。 查询结果格式示例如下: 解题思路 1.题目要…

ERROR 1064 - You have an error in your SQL syntax;

ERROR 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near (/, 少个逗号吧,以前开始写SQL,特别是修改SQL的时候容易出现这样错误。 而且自己也知道在附近…

Qt6.5.2+WebRTC学习笔记(十三)开发环境搭建(macOS13.5)

前言 在ubuntu和win10开发测试一段时间了,但总在存在平台特性的问题,所以准备将程序移植到macOS上测试,同步进行三个主要桌面系统开发,本教程记录下环境搭建过程 一、准备 1.操作系统macOS13.5 64位 x86架构(建议系…

python多线程

目录 一.多线程的定义 A.什么是多线程? B.多线程如今遇到的挑战 C.总结 二.python中的多线程 A.python中的多线程底层原理: B.全局解释器锁导致python多线程不能实现真正的并行执行! C.总结应用场景 三.java多线程,以及…

每日一题——删除有序数组中的重复项

删除有序数组中的重复项 题目链接 注:本题所采用的方法是建立在移除元素的基础之上的,如果大家对双指针的方法不大了解,或者不会做《移除元素》这一题,建议先去看看👉传送门 具体步骤 定义两个指针slow和fast&#…

如何在3ds max中创建可用于真人场景的巨型机器人:第 2 部分

推荐: NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. 创建主体 步骤 1 打开 3ds Max。选择机器人头部后,二次单击鼠标并选择隐藏未选中。机器人的其他部分 除了头部之外,将被隐藏。 打开 3ds Max 步骤 2 在人脸选择模式下&#x…

使用 Logstash 及 enrich processor 实现数据丰富自动化

在我之前的文章: Elasticsearch:enrich processor (7.5发行版新功能) Elasticsearch:使用 Elasticsearch ingest pipeline 丰富数据 通过上面的两篇文章的介绍,我们应该充分掌握了如何使用 enrich proce…

深度探索 Elasticsearch 8.X:function_score 参数解读与实战案例分析

在 Elasticsearch 中,function_score 可以让我们在查询的同时对搜索结果进行自定义评分。 function_score 提供了一系列的参数和函数让我们可以根据需求灵活地进行设置。 近期有同学反馈,function_score 的相关参数不好理解,本文将深入探讨 f…

重排链表——力扣143

文章目录 题目描述法一:寻找链表中点、链表逆序、链表合并 题目描述 法一:寻找链表中点、链表逆序、链表合并 void reorderList(ListNode* head){if(headnullptr){return;}// 找到中点 ListNode* mid FindMiddle(head);ListNode *h1head, *h2mid->ne…

tinkerCAD案例:22. Backpack Zipper Pull 背包拉链头

tinkerCAD案例:21. Custom Stamp 定制印章 原文 tinkerCAD案例:22. Backpack Zipper Pull 背包拉链头 Lesson Overview: 课程概述: Now we’re going to make a zipper pull! 现在我们要做一个拉链头! Your backpack, howev…

金融行业软件测试面试题及其答案

下面是一些常见的金融行业软件测试面试题及其答案: 1. 什么是金融行业软件测试? 金融行业软件测试是针对金融领域的软件系统进行验证和确认的过程,旨在确保软件在安全、稳定、可靠和符合法规要求的条件下运行。 2. 解释一下金融软件中的风险…

代码随想录算法训练营day15 | 102. 二叉树的层序遍历,226. 翻转二叉树,101. 对称二叉树

目录 102. 二叉树的层序遍历 226. 翻转二叉树 101. 对称二叉树 100. 相同的树 100是101的衍生题目。572也为101的衍生题目。 102. 二叉树的层序遍历 思路&#xff1a; 以前的笔记 代码&#xff1a; class Solution {public List<List<Integer>> levelOrder(T…

卸载大脑,相信DFS

切莫相信动规&#xff0c;吾将为您指明前进之路 印子 比赛时&#xff0c;你是否有这样的经历&#xff1a;不敢用for暴搜&#xff0c;又不会用数学公式推理&#xff1b;焦急地在纸上打草&#xff0c;却没有优化思路&#xff1b;明明比赛前一天晚上背了那么多模板却脑子一片空白…

生成模型和判别模型工作原理介绍

您解决的大多数机器学习和深度学习问题都是从生成模型和判别模型中概念化的。在机器学习中,人们可以清楚地区分两种建模类型: 将图像分类为狗或猫属于判别性建模生成逼真的狗或猫图像是一个生成建模问题神经网络被采用得越多,生成域和判别域就增长得越多。要理解基于这些模型…

Python Web开发技巧VIII

目录 ModelSerializer和Serializer区别是什么 从queryset中取出某个models的字段值 Q对象进行模糊匹配 HTTP方式-如何模糊搜索JSON字段中的某个KEY值呢&#xff1f; showmigrations 合并两个或多个queryset ModelSerializer和Serializer区别是什么 都是DRF中用于序列化和…

QT【day3】

思维导图&#xff1a; 闹钟&#xff1a; //widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> // #include<QTime> //定时器 #include<QDebug> // #in…

力扣算法数学类—剑指 Offer 43. 1~n 整数中 1 出现的次数

目录 剑指 Offer 43. 1&#xff5e;n 整数中 1 出现的次数 题解&#xff1a; 代码&#xff1a; 结果&#xff1a; 输入一个整数 n &#xff0c;求1&#xff5e;n这n个整数的十进制表示中1出现的次数。 例如&#xff0c;输入12&#xff0c;1&#xff5e;12这些整数中包含1 的…