Nginx反向代理websocket

示例:

http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
} server {
... location /chat/ {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}

也许你也曾遇到为什么配置ws/wss协议相关的代理时总是不顺利?最后一番搜索发现需要加上面三行,于是二话不讲,ctrl+c/ctrl+v 一套带走,reload一下, 完成了。

那么这三行到底有什么特殊本领呢?简单看看:

proxy_http_version 1.1;

这一行没啥说的,设置http协议版本1.1, 这个主要是为了下面的两行做准备。

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

这两行就是设置两个请求头 UpgradeConnection,这两个请求头都是逐跳标头(只能传输一次,不能透传), 后端ws程序根据这两个头携带的信息来判断是否使用ws协议来通信。

  • Upgrade

    能且只能在http1.1版本中使用, 用来标识协议升级/转换, 在我们这篇文章的背景下,这个头信息一般是: Upgrade: websocket; 表示客户端希望使用websocket协议通信, 那么后端的ws程序取到头信息后会返回101状态码(协议转换),此时浏览器就会使用当前的TCP连接建立websocket通道。

  • Connection

    在本篇文章的背景下, Connection头信息取值upgrade, 表示本次请求是一次协议升级(协议转换)请求, 配合 Upgrade: websocket信息, 完整表达了这个请求要升级到websocket协议。

为什么要显示指定升级头?

上面提到了反向代理和逐跳标头,客户端发起请求时是和反响代理服务器建立请求, 此时客户端携带的 Upgrade、Connection头是不会被反向代理服务器直接转发到后端服务的(这就是逐跳标头), 后端服务获取不到这两个头信息自然也不会主动去切换协议。

因此,需要在反向代理服务器转发上游时带上客户端原来的请求头,才可以完成协议的升级或切换。

容易遇到的问题

  1. 需要注意多层反向代理的场景,都要显示指定头信息才行,否则不得行。
  2. wss只要在最外层的代理服务器上配置即可, 内层的代理服务器使用ws协议交互。

最新文章

  1. android Acitivity之间的几种传值方式(^_^)
  2. FFT入门
  3. 条件变量pthread_cond_t怎么用
  4. Mybatis 开启事务@Transactional
  5. ios中怎么样调节占位文字与字体大小在同一高度
  6. DelegatingFilterProxy
  7. CheckedListBox与下拉框联动代码
  8. bootstrap -- 一个标签中,同时有 col-xs , col-sm , col-md , col-lg
  9. 网络层 IP 协议首部格式与其配套使用的四个协议(ARP,RARP,ICMP,IGMP)
  10. weui.css中flex容器下子项目的水平和垂直居中
  11. Unity3D判断触摸方向
  12. Servlet(九):web.xml文件和server.xml文件
  13. Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified and no embedded datasource could be auto-configured.
  14. [MapReduce_5] MapReduce 中的 Combiner 组件应用
  15. 移动开发--viewport
  16. srbac配置
  17. GPUImage中对比度调整的实现——GPUImageContrastFilter
  18. Ant.OutputIsUnreadableCode
  19. 关于curl: (2) Failed Initialization
  20. 关联容器map(红黑树,key/value),以及所有的STL容器详解

热门文章

  1. mybatis-03-一对多关系映射(附源码)
  2. #define的3种用法详解
  3. kbengine开源分布式游戏服务端引擎
  4. 人机交互大作业--flash嵌入web(纯界面)
  5. 假期任务一:安装好JAVA开发环境并且在Eclipse上面成功运行HelloWorld程序
  6. node安装和环境配置
  7. vue中图片预览(v-viewer库使用)
  8. Taro时间选择器+地址选择器
  9. 手撕spring核心源码,彻底搞懂spring流程
  10. 使用SQL的FOR XML PATH('')将字段用逗号隔开