websocket 404错误主因是nginx未透传upgrade和connection头,导致握手请求被当作普通http处理而返回404;需在location块中配置proxy_http_version 1.1、proxy_set_header upgrade $http_upgrade、proxy_set_header connection "upgrade"。

WebSocket 404 错误不是服务没起来,而是客户端发出去的 Upgrade 请求被中间层(Nginx / Spring / Laravel Echo)拦下来或转错了——它压根没到你的 @ServerEndpoint 或 WebSocketHandler 那儿。
WebSocket 地址里带不带 context-path?
很多 Spring Boot 项目打成 WAR 包扔进 Tomcat,或者用了 server.servlet.context-path=/api,这时候你写的 @ServerEndpoint("/chat") 实际暴露路径是 /api/chat,但前端连的还是 ws://host/chat,必然 404。
- 查清后端真实暴露路径:启动时看日志有没有类似
Registered @ServerEndpoint at /api/chat;或者 curlhttp://localhost:8080/actuator/mappings(Spring Boot Actuator)搜websocket - 前端
new WebSocket()的 URL 必须和这个完整路径对齐,比如后端是/api/chat,前端就得写ws://host/api/chat - Laravel + laravel-websockets 场景下,
wsHost和wsPort是服务器地址,而实际连接路径由authEndpoint和 socket 连接路径共同决定,不能只看wsHost
Nginx 反向代理漏了 Upgrade 头
这是线上环境最常踩的坑。Nginx 默认把 WebSocket 握手当普通 HTTP 请求处理,Upgrade 和 Connection 这两个关键 header 被丢弃,后端收不到升级意图,直接返回 404(因为没匹配到任何 HTTP 路由)。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 必须在
location块里显式加这三行:proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade"; - 别写成
Connection "Upgrade"(首字母大写)——某些 Nginx 版本会失败 - 如果用了
proxy_cache,务必关掉:proxy_cache off;,缓存会破坏 WebSocket 握手流程 - 确认 Nginx 版本 ≥ 1.3.13,老版本不支持
proxy_http_version 1.1
Laravel Echo 的 wsHost 和真实 WebSocket 服务地址不一致
用 laravel-echo + laravel-websockets 时,wsHost 不是你 Laravel API 的域名,而是 WebSocket 服务监听的地址——它可能和 API 不在一个机器、甚至不是同一个端口。
- 默认情况下,
laravel-websockets启动后监听0.0.0.0:6001,所以wsHost应该填部署这台服务的 IP 或域名,不是api.example.com - 如果你把
laravel-websockets和 Laravel API 部署在同一台机器但不同端口,且没开公网端口映射,前端根本连不到 6001 —— 此时要么配 Nginx 反代/ws到6001,要么改wsHost为反代后的地址 -
key字段必须和config/broadcasting.php里的pusher.key完全一致,否则认证端点(/laravel-websockets/auth)会 404 或 403
Spring Boot 的 @ServerEndpoint 没被扫描到
Spring Boot 默认不自动注册 JSR-356 的 @ServerEndpoint 类,哪怕你加了 spring-boot-starter-websocket 依赖,也得手动导出。
- 必须声明一个
@Bean返回ServerEndpointExporter,否则 Tomcat 启动时根本不会加载你的 endpoint - 检查类上有没有
@Component(非必须,但推荐),以及是否被 Spring 扫描到(包路径是否在@SpringBootApplication同级或子级) - 如果用了嵌入式 Tomcat,确保没禁用 WebSocket 支持:
server.tomcat.additional-tld-skip-patterns=*.jar这类配置可能意外跳过 websocket-api.jar - 用
@EnableWebSocket+WebSocketConfigurer是另一套配置方式,和@ServerEndpoint互斥,别混着用
真正卡住人的地方,往往不是代码写错,而是「以为走的是 A 路径,其实请求早被 Nginx / Spring Boot / Laravel Echo 在半路截胡了」——先抓包看握手请求到底发去了哪儿、带了哪些 header、响应是什么,比盲调配置快得多。










