带有 lb 的 Aws ec2 不会在 websocket 上返回 101
Posted
技术标签:
【中文标题】带有 lb 的 Aws ec2 不会在 websocket 上返回 101【英文标题】:Aws ec2 with lb does not return 101 on websocket 【发布时间】: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";
提前致谢!
【问题讨论】:
【参考方案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 是的,检查一下。无论如何,谢谢。 用你应该记录的内容更新了答案以上是关于带有 lb 的 Aws ec2 不会在 websocket 上返回 101的主要内容,如果未能解决你的问题,请参考以下文章
AWS - ECS - 如何在现有 ECS(带有 1 个 EC2)实例上重新部署更新的 Docker 映像?
带有 PHP SDK 的 AWS EC2 - 等到实例具有公共 DNS 名称
text 带有docker post命令的AWS EC2简单AMI
在 AWS CloudFormation 模板中,如何使用自己的 Id 标记 EC2 实例而不会出现循环引用错误?
在某些情况下,AWS ELB 不会将请求分发到 Auto Scaling 组 EC2 实例
NVidia 驱动程序停止在带有 Ubuntu 16.04 和 Tesla K80 GPU 的 AWS EC2 实例上工作