Go WebSocket 简易测试代码 Docker 进阶版本

19 min read

目录结构

├── Dockerfile
├── README.md
├── docker-compose.yaml
├── go.mod
├── go.sum
├── index.html
├── main.go
├── nginx.conf

Docker-compose 文件

version: '3'
services:
  nginx:
    image: nginx
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
    ports:
      - 9980:80
    privileged: true

  test:
    build:
      context: .
    ports:
      - 9981:8088
  • 加载本地 nginx 配置
  • 9980 -> 转发到nginx80 -> 代理到后端 go 的 8088 ws端口
  • 9981-> go的后端服务

nginx 配置

#user  nobody;

worker_processes  2;

#工作模式及连接数上线
events {
    worker_connections  1024;  #设置最大连接数
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    #sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用,
    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    # 开启GZIP
    gzip  on;

    #必须添加的
    map $http_upgrade $connection_upgrade {
            default upgrade;
            '' close;
    }

    upstream websocket {
        #转发到服务器上相应的ws端口
        server test:8088;
    }

    # # 监听 80 端口,转发请求到 3000 端口
    server {
        #监听端口
        listen    80;
        #编码格式
        charset utf-8;

       location /ws {
        #转发到http://websocket
        proxy_pass http://websocket;
        proxy_read_timeout 300s;
        proxy_send_timeout 300s;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        #升级http1.1到 websocket协议  
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection  $connection_upgrade;
    }
    }
}
  • 使用test域访问后端go服务
  • 转发到http://websocket upstream websocket

服务端

package main

import (
	"fmt"
	"net/http"

	"github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

func main() {
	http.HandleFunc("/echo", func(w http.ResponseWriter, r *http.Request) {
		conn, _ := upgrader.Upgrade(w, r, nil) // error ignored for sake of simplicity

		for {
			// Read message from browser
			msgType, msg, err := conn.ReadMessage()
			if err != nil {
				return
			}

			// Print the message to the console
			fmt.Printf("%s sent: %s\n", conn.RemoteAddr(), string(msg))

			// Write message back to browser
			if err = conn.WriteMessage(msgType, msg); err != nil {
				return
			}
		}
	})

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.ServeFile(w, r, "index.html")
	})

	http.ListenAndServe(":8088", nil)
}

html 文件

<meta charset="utf-8"/>
<input id="input" type="text" />
<button onclick="send()">Send</button>
<pre id="output"></pre>
<script>
    var input = document.getElementById("input");
    var output = document.getElementById("output");
    var socket = new WebSocket("ws://localhost:9981/echo");

    socket.onopen = function () {
        output.innerHTML += "Status: Connected\n";
    };

    socket.onmessage = function (e) {
        output.innerHTML += "Server: " + e.data+1 + "\n";
    };

    function send() {
        socket.send(input.value);
        input.value = "";
    }
</script>