领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多最后更新于 2012年11月5日 (Spring MVC 3.2 RC1)
在我上一篇文章中,我介绍了 Spring MVC 3.2 中新的基于 Servlet 3 的异步支持,并讨论了长时间运行的请求。异步处理的第二个非常重要的动机是浏览器需要接收实时更新。示例包括浏览器中的聊天、股票行情、状态更新、实时体育赛事结果等。当然,并非所有示例都同样对延迟敏感,但它们都具有类似的需求。
在标准的 HTTP 请求-响应语义中,浏览器发起请求,服务器发送响应,这意味着服务器在收到浏览器的请求之前无法发送新信息。已经发展出几种方法,包括传统轮询、长轮询和HTTP 流,最近还有WebSocket 协议。
传统轮询
浏览器不断发送请求以检查新信息,服务器每次都立即响应。这适用于可以以相当稀疏的间隔进行轮询的场景。例如,邮件客户端可以每 10 分钟检查一次新邮件。它很简单,而且有效。但是,当需要尽快显示新信息时,这种方法效率低下,在这种情况下,轮询必须非常频繁。
长轮询
浏览器不断发送请求,但服务器只有在有新信息要发送时才响应。从客户端的角度来看,这与传统轮询相同。从服务器的角度来看,这非常类似于长时间运行的请求,可以使用第一部分中讨论的技术进行扩展。
响应可以保持打开多长时间?浏览器设置为在 5 分钟后超时,而代理等网络中间件可能会更早超时。因此,即使没有新的信息到达,长轮询请求也应该定期完成,以允许浏览器发送新的请求。这IETF 文档建议使用 30 到 120 秒之间的超时值,但实际使用的值可能取决于您对将浏览器与服务器分开的网络中间件的控制程度。
长轮询可以显著减少接收低延迟信息更新所需的请求数量,尤其是在新信息以不规则间隔出现的情况下。但是,更新越频繁,它就越接近传统轮询。
HTTP 流
浏览器向服务器发送请求,服务器在有信息要发送时响应。但是,与长轮询不同,服务器保持响应打开并继续发送到达的更多更新。这种方法消除了轮询的需要,但也与典型的 HTTP 请求-响应语义有更大的偏离。例如,客户端和服务器需要就如何解释响应流达成一致,以便客户端知道一个更新在哪里结束,另一个更新在哪里开始。此外,网络中间件可以缓存响应流,这会破坏该方法的意图。这就是为什么长轮询在今天更常用。
WebSocket 协议
浏览器向服务器发送 HTTP 请求以切换到 WebSocket 协议,服务器通过确认升级进行响应。此后,浏览器和服务器可以在 TCP 套接字上双向发送数据帧。
WebSocket 协议旨在取代轮询的需要,特别适用于需要在浏览器和服务器之间高频率交换消息的场景。通过 HTTP 的初始握手确保 WebSocket 请求可以穿过防火墙。但是,也存在重大挑战,因为大多数已部署的浏览器不支持 WebSockets,并且在通过网络中间件方面存在进一步的问题。
WebSockets围绕文本或二进制消息的双向交换展开。它导致了一种与基于 RESTful 的 HTTP 架构显著不同的方法。事实上,需要在 WebSockets 之上使用另一种协议,例如 XMPP、AMQP、STOMP 或其他协议,哪些协议将成为主流还有待观察。
WebSocket 协议 已经由 IETF 标准化,而 WebSocket API 正在由 W3C 标准化的最后阶段。许多 Java 实现已经可用,包括 Jetty 和 Tomcat 等 servlet 容器。Servlet 3.1 规范可能会支持初始 WebSocket 升级请求,而单独的 JSR-356 将定义基于 Java 的 WebSocket API。
回到 Spring MVC 3.2,Servlet 3 异步特性可用于长时间运行的请求以及 HTTP 流,Filip Hanik 称之为“客户端 AJAX 调用的服务器版本”。至于 WebSockets,Spring 3.2 中尚不支持,但很可能会包含在 Spring 3.3 中。您可以关注 SPR-9356 以获取进度更新。
下一篇文章 将转向示例代码,并更详细地解释新的 Spring MVC 3.2 功能。