使用Nginx对Websocket进行反向代理

背景

在Vue项目中,开发websocket时,将IP和端口号固定,或者根据NODE_ENV判断环境,修改IP和端口,相当不可取。当环境地址变更时,就需要重新打包,再发布版本,很是麻烦。使用Nginx对WebSocket进行反向代理,就会解决这一痛点问题。Nginx从1.3.13版本开始支持对Websocket进行反向代理。

Nginx配置示例

<html>
<body>
<script>
  let wsServer = `${location.protocol === 'https' ? 'wss' : 'ws'}://${location.host}/websocket/order`
  let websocket = new WebSocket(wsServer)
  websocket.onopen = function (evt) { onOpen(evt) }
  websocket.onclose = function (evt) { onClose(evt) }
  websocket.onmessage = function (evt) { onMessage(evt) }
  websocket.onerror = function (evt) { onError(evt) }
  function onOpen (evt) {
	console.log('Connected to WebSocket server.')
  }
  function onClose (evt) {
	console.log('Disconnected')
  }
  function onMessage (evt) {
	console.log('Retrieved data from server: ' + evt.data)
  }
  function onError (evt) {
	console.log('Error occured: ' + evt.data)
  }
</script>
</body>
</html>

Nginx配置文件。官网文档

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    
    map $http_upgrade $connection_upgrade {
		default upgrade;
		''      close;
	}
	
    server {
        listen       9001;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
        }

        location ^~ /websocket {
            proxy_pass http://localhost:8090/;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_read_timeout 120s;

            proxy_set_header Upgrade websocket;
            proxy_set_header Connection Upgrade;
        }
    }
}

关键配置说明

map $http_upgrade $connection_upgrade {
default upgrade;
‘’ close;
}

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;

以上配置的作用是在HTTP请求中增加头部

Upgrade: websocket
Connection: Upgrade

默认情况下,连接将会在无数据传输60秒后关闭,proxy_read_timeout参数可以延长这个时间。

Vue配置示例

<template>
  <div class="home">
  </div>
</template>

<script>
export default {
  name: 'home',
  created () {
    this.init()
  },
  methods: {
    init () {
      let wsServer = `${location.protocol === 'https' ? 'wss' : 'ws'}://${location.host}/websocket/order`
      let websocket = new WebSocket(wsServer)
      websocket.onopen = function (evt) { onOpen(evt) }
      websocket.onclose = function (evt) { onClose(evt) }
      websocket.onmessage = function (evt) { onMessage(evt) }
      websocket.onerror = function (evt) { onError(evt) }
      function onOpen (evt) {
        console.log('Connected to WebSocket server.')
      }
      function onClose (evt) {
        console.log('Disconnected')
      }
      function onMessage (evt) {
        console.log('Retrieved data from server: ' + evt.data)
      }
      function onError (evt) {
        console.log('Error occured: ' + evt.data)
      }
    }
  }
}
</script>

vue.config.js 配置

module.exports = {
    devServer: {
        proxy: {
          '/websocket': {
                target: 'http://localhost:8090',
                ws: true,
                changeOrigin: true,
                pathRewrite: {
                    '^/websocket': ''
                },
            },
        }
    }
}
Logo

前往低代码交流专区

更多推荐