Сбой подключения WebSocket с 301 при использовании Go on AWS Application Load Balancer

Я пытаюсь запустить сервер Go с WebSockets на балансировщике нагрузки приложений AWS, но получаю сообщение «Ошибка при рукопожатии WebSocket: неожиданный код ответа: 301».

AWS сообщает, что балансировщики нагрузки приложений поддерживают WebSockets через протоколы ws: //, но я не могу найти никакой дополнительной документации, кроме следующей:

Вот ссылка на балансировщик нагрузки aws

Балансировщик нагрузки приложений поддерживает два дополнительных протокола: WebSocket и HTTP / 2.

WebSocket позволяет вам устанавливать давние TCP-соединения между вашим клиентом и вашим сервером. Это более эффективная альтернатива методу старой школы, который включал HTTP-соединения, которые оставались открытыми с «биением сердца» в течение очень долгих периодов времени. WebSocket отлично подходит для мобильных устройств и может использоваться для доставки котировок акций, результатов спортивных соревнований и других динамических данных при минимальном потреблении энергии. ALB обеспечивает встроенную поддержку WebSocket через протоколы ws: // и wss: //.

Я могу заставить JavaScript подключаться к моему серверу Go локально через WebSockets, но когда я развертываю AWS, он не работает. Это когда JavaScript отображает ошибку 301.

Балансировщик нагрузки приложения прослушивает HTTP: 80, и этот трафик направляется на HTTPS: 443. Все группы безопасности настроены примерно одинаково для пропуска трафика. Если я выполняю обычный вызов GET для получения данных с моего сервера во время развертывания на AWS, он работает отлично.

Локальный вызов, который работает для подключения к localhost

<script>
    let socket = new WebSocket("ws://localhost:8080/websocket")

    console.log("Attempting Websocket Connection")

    socket.onopen = () => {
        console.log("Successfully Connected");
        socket.send("Hi From the Client!")
    }

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

    socket.onmessage = (msg) => {
        console.log(msg);
    }

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

Подключитесь к удаленному серверу, который не работает.

<script>
    let socket = new WebSocket("ws://myexamplesite.com/websocket")

    console.log("Attempting Websocket Connection")

    socket.onopen = () => {
        console.log("Successfully Connected");
        socket.send("Hi From the Client!")
    }

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

    socket.onmessage = (msg) => {
        console.log(msg);
    }

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

nginx.conf

events {
    worker_connections 1024;
}

http {
  server_tokens off;
  server {
    listen 80;

    location / {
      proxy_set_header X-Forwarded-For $remote_addr;
      proxy_set_header Host            $http_host;
      proxy_pass http://web:8080/;
    }
  }
}

Я ожидаю, что смогу установить соединение WebSocket, но из файла JavaScript возвращается следующая ошибка:

Соединение WebSocket с 'ws: //myexamplesite.com/websocket' не удалось: ошибка при рукопожатии WebSocket: неожиданный код ответа: 301


person CJMobileApps    schedule 15.09.2019    source источник
comment
этот трафик направляется на HTTPS предположительно означает перенаправление, и если да, то это прекрасно объясняет, почему вы получаете 301. Измените URL-адрес веб-сокета на wss:// - let socket = new WebSocket("wss://....   -  person Michael - sqlbot    schedule 16.09.2019
comment
@ Michael-sqlbot Спасибо, это сработало!   -  person CJMobileApps    schedule 17.09.2019


Ответы (2)


Сначала убедитесь, что у вас все правильно с точки зрения конфигурации AWS ALB и что запросы достигают сервера Nginx, что вы можете проверить в журналах. Также попробуйте попасть в URL-адрес вашего веб-сокета через Nginx. Вам понадобится дополнительная конфигурация в Nginx для поддержки веб-сокетов под вашим местоположением, как указано здесь:

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";

У меня возникла та же проблема, и использование этой конфигурации начало работать как ветер.

Ссылка: Nginx WebSocket Proxying

Примечание. Веб-сокеты наверняка работают с AWS ALB, поэтому не сомневайтесь в этом.

person Juned Ahsan    schedule 15.09.2019
comment
Это частично сработало, также пришлось изменить ws: // на wss: // - person CJMobileApps; 17.09.2019

Мне удалось заставить его работать, объединив оба ответа.

nginx.conf теперь выглядит как

http {
  server_tokens off;
  server {
    listen 80;

    location / {
      proxy_set_header X-Forwarded-For $remote_addr;
      proxy_set_header Host            $http_host;
      proxy_pass http://web:8080/;
    }

    location /websocket {
           proxy_http_version 1.1;
           proxy_set_header Upgrade $http_upgrade;
           proxy_set_header Connection "upgrade";
           proxy_pass http://web:8080/websocket;
    }
  }
}

Затем измените файл JavaScript ws: // на wss: //.

<script>
    let socket = new WebSocket("wss://myexamplesite.com/websocket")

    console.log("Attempting Websocket Connection")

    socket.onopen = () => {
        console.log("Successfully Connected");
        socket.send("Hi From the Client!")
    }

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

    socket.onmessage = (msg) => {
        console.log(msg);
    }

    socket.onerror = (error) => {
        console.log("Socket Error: ", error)
    }
</script>
person CJMobileApps    schedule 17.09.2019