|
对于最新的稳定版本,请使用 Spring Framework 7.0.6! |
WebSockets
这部分参考文档涵盖了对Servlet堆栈的支持,WebSocket消息传递,包括原始的WebSocket交互,通过SockJS进行的WebSocket模拟,以及通过STOMP作为WebSocket上的子协议实现的发布-订阅消息传递。
WebSocket简介
WebSocket协议,RFC 6455,提供了一种标准化的方式,用于在客户端和服务器之间通过单个TCP连接建立全双工、双向通信通道。它与HTTP是不同的TCP协议,但设计为通过HTTP工作,使用端口80和443,并允许重用现有的防火墙规则。
WebSocket 交互从使用 HTTP Upgrade 头的 HTTP 请求开始,以升级或在这种情况下切换到 WebSocket 协议。以下示例显示了这样的交互:
GET /spring-websocket-portfolio/portfolio HTTP/1.1
Host: localhost:8080
Upgrade: websocket (1)
Connection: Upgrade (2)
Sec-WebSocket-Key: Uc9l9TMkWGbHFD2qnFHltg==
Sec-WebSocket-Protocol: v10.stomp, v11.stomp
Sec-WebSocket-Version: 13
Origin: http://localhost:8080
| 1 | 核心 Upgrade 标头。 |
| 2 | 使用 Upgrade 连接。 |
与通常的200状态码不同,支持WebSocket的服务器返回的输出类似于以下内容:
HTTP/1.1 101 Switching Protocols (1)
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: 1qVdfYHU9hPOl4JYYNXF623Gzn0=
Sec-WebSocket-Protocol: v10.stomp
| 1 | 协议切换 |
成功握手后,HTTP升级请求底层的TCP套接字保持打开状态,客户端和服务器可以继续发送和接收消息。
关于WebSockets的工作原理的完整介绍超出了本文档的范围。请参阅RFC 6455、HTML5中的WebSocket章节,或网络上的众多介绍和教程。
请注意,如果WebSocket服务器运行在Web服务器(例如nginx)后面,您可能需要配置它以将WebSocket升级请求传递给WebSocket服务器。同样,如果应用程序在云环境中运行,请查看云提供商关于WebSocket支持的相关说明。
HTTP与WebSocket对比
尽管WebSocket被设计为与HTTP兼容并以HTTP请求开始,但重要的是要理解这两种协议会导致非常不同的架构和应用程序编程模型。
在HTTP和REST中,应用程序被建模为许多URL。要与应用程序交互,客户端访问这些URL,采用请求-响应的方式。服务器根据HTTP URL、方法和标头将请求路由到适当的处理器。
相比之下,在WebSockets中,通常只有一个URL用于初始连接。 随后,所有应用程序消息都在同一个TCP连接上流动。这指向了一种完全不同的异步、事件驱动的消息架构。
WebSocket 也是一种低级别的传输协议,与 HTTP 不同,它不对消息内容规定任何语义。这意味着除非客户端和服务器就消息语义达成一致,否则无法路由或处理消息。
WebSocket 客户端和服务器可以通过 HTTP 握手请求中的 Sec-WebSocket-Protocol 头部协商使用更高层级的消息协议(例如,STOMP)。如果没有这个头部,它们需要自己制定约定。
何时使用WebSockets
WebSockets 可以使网页变得动态和互动。然而,在许多情况下,Ajax 和 HTTP 流或长轮询的组合可以提供一个简单而有效的解决方案。
例如,新闻、邮件和社交动态需要动态更新,但每隔几分钟更新一次可能是完全可以接受的。另一方面,协作、游戏和金融应用程序需要更接近实时。
延迟本身并不是决定性因素。如果消息量相对较低(例如,监控网络故障),HTTP流或轮询可以提供有效的解决方案。正是低延迟、高频率和高容量的结合使得使用WebSocket成为最佳选择。
请记住,通过互联网,您无法控制的限制性代理可能会阻止WebSocket交互,要么是因为它们没有配置为传递Upgrade标头,要么是因为它们关闭了看起来空闲的长连接。这意味着在防火墙内的内部应用程序中使用WebSocket是一个更直接的决定,而不是在面向公众的应用程序中。