【问题标题】:Aws ec2 with lb does not return 101 on websocket带有 lb 的 Aws ec2 不会在 websocket 上返回 101
【发布时间】:2022-01-24 06:56:03
【问题描述】:

我的应用程序有问题。 基本上,虽然一切都在本地主机上运行顺利,但当我部署到 aws websocket 连接不起作用。 问题是,当我在 ec2 上发出 wss 请求时,它似乎确实让响应离开了机器,所以我的应用程序没有变成 101 并稳定连接,而是挂起等待 1 分钟过去并获得超时,然后它返回 200 但没有建立连接。 Api 是用 go lang 和 gin 框架编写的,app 是用 js 和 React 框架编写的。 在询问一些人的建议时,他们告诉我,我可以用 https“包装”一个 wss 请求,然后通过 lb 传递它并用 nginx 升级它,但我真的找不到类似的东西。 这是我的后端代码

main.go

    {

        ws.GET("/:id", func(c *gin.Context) {
            websocket.ServeWs(c, pool)
        })
    }

websocket.go

ar upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
    CheckOrigin: func(r *http.Request) bool { return true },
}

func Upgrade(w http.ResponseWriter, r *http.Request) (*websocket.Conn, error) {
    ws, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println(err)
        return ws, err
    }
    return ws, nil
}

func ServeWs(c *gin.Context, pool *Pool) {

    w := c.Writer
    r := c.Request
    conn, err := Upgrade(w, r)
    if err != nil {
        fmt.Fprintf(w, "%+V\n", err)
    }
    client := &Client{
        Conn: conn,
        Pool: pool,
        ID: c.Param("id"),
    }

    pool.Register <- client
    client.Read()
}

这是反应代码

const socket = new WebSocket(
  `${
    process.env.REACT_APP_ENV === "dev"
      ? "ws://localhost:8080"
      : "wss://api.blabla.prod"
  }/ws/${sessionStorage.getItem("userID")}`
);


let WebSocketConnect = () => {
  console.log("Attempting Connection...");

  socket.onopen = () => {
    console.log("Successfully Connected");
  };

  socket.onclose = (event) => {
    console.log("Socket Closed Connection: ", event);
    // WebSocketConnect();
  };

  socket.onerror = (error) => {
    console.log("Socket Error: ", error);
  };
};

let sendMsg = (msg) => {
  //   console.log("sending msg: ", msg);
  socket.send(msg);
};

export { WebSocketConnect, sendMsg, socket };

这里是 nginx 配置

server {

    listen 80;
    server_name api.blabla.prod;

    if ($http_x_forwarded_proto = 'http') {
        return 301 https://$server_name$request_uri;
    }
    location /ws {
        proxy_pass "http://127.0.0.1:8080";
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
    location / {
        proxy_set_header X-Forwarded-For $remote_addr;
        proxy_set_header Host $http_host;
        proxy_pass       "http://127.0.0.1:8080";
    }
}

提前致谢!

【问题讨论】:

    标签: reactjs amazon-web-services go nginx websocket


    【解决方案1】:

    问题似乎出在您的 nginx 配置中,我会为您的 /ws 端点复制此问题。好像少了$proxy_add_x_forwarded_for

    server {
            listen 80;
            server_name goddit.pro; // change this
            location / { // You can leave it at / or set it for another location, i.e. /ws
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header Host $http_host;
                    proxy_set_header X-NginX-Proxy true;
    
                    proxy_pass http://localhost:8080/;
                    proxy_redirect off;
    
                    proxy_http_version 1.1;
                    proxy_set_header Upgrade $http_upgrade;
                    proxy_set_header Connection "upgrade";
            }
    }
    

    问题也可能出在您的 JavaScript 中,这是您连接和升级的方式。

    window.onload = function () {
      // Somewhere in your HTML document
      var conn;
      // Then you need to connect
      function connectWs(id) {
        if (window["WebSocket"]) {
          conn = new WebSocket("wss://" + document.location.host + "/id/" + id);
          conn.onopen = function (evt) {
            var item = document.createElement("li");
            item.innerHTML = "<em>Connected to " + id + "</em>";
            log.appendChild(item);
          };
          conn.onclose = function (evt) {
            var item = document.createElement("li");
            item.innerHTML = "<em>Connection to " + id + " closed</em>";
            log.appendChild(item);
          };
          conn.onmessage = function (evt) {
            var message = JSON.parse(evt.data);
            // console.log(message);
            printMessage(message);
          };
        } else {
          var item = document.createElement("li");
          item.innerHTML = "<b>Your browser does not support WebSockets.</b>";
          log.appendChild(item);
        }
      }
      connectWs(id);
    }
    

    从 React 控制台共享错误日志后:

    关闭Code 1006 是一个特殊代码,表示连接被浏览器实现异常(本地)关闭。

    如果您的浏览器客户端报告关闭代码 1006,那么您应该查看 websocket.onerror(evt) 事件以了解详细信息。

    【讨论】:

    • 没有任何变化,请求确实通过了 nginx,但没有立即返回。如果这有助于 /ws 的日志是这个 ` [GIN] 2021/12/23 - 08:56:38 | 200 | 59.658382116s | 172.31.40.164 | GET "/ws/admin" 连接池大小: 0 2021/12/23 08:56:38 发生错误: websocket: close 1006 (异常关闭): unexpected EOF`
    • 你确定你用那个重启了你的 nginx 等吗?它缺少标头、代理重定向等。
    • 是的 sudo systemctl restart nginx
    • 是的,检查一下。无论如何,谢谢。
    • 用你应该记录的内容更新了答案
    猜你喜欢
    • 2017-03-23
    • 2020-10-10
    • 2020-08-27
    • 2019-06-29
    • 1970-01-01
    • 2014-07-28
    • 1970-01-01
    • 2013-04-01
    • 2021-04-11
    相关资源
    最近更新 更多