http 服务器将如何处理 html5 网络套接字?
Posted
技术标签:
【中文标题】http 服务器将如何处理 html5 网络套接字?【英文标题】:How will http server handle html5 web sockets? 【发布时间】:2010-07-08 09:25:02 【问题描述】:我阅读了很多有关 html5 的内容,我特别喜欢 Web 套接字,因为它们促进了 Web 服务器和 Web 浏览器之间的双向通信。
但我们一直在阅读有关 chrome、opera、firefox、safari 为 html5 做好准备的信息。哪个 Web 服务器已准备好使用 Web 套接字功能?我的意思是,截至今天,Web 服务器是否能够启动后续通信? Google自己的Appengine怎么样?
如何编写一个利用 Java 中此功能的示例 Web 应用程序?
【问题讨论】:
【参考方案1】:Web 服务器和浏览器之间的双向通信并不是什么新鲜事。如果您正在阅读的问题发布了新答案,Stack Overflow 今天就会这样做。使用现有技术实现套接字样式行为有几种不同的策略:
AJAX 短轮询:连接到服务器并询问是否有任何新消息。如果没有,请立即断开连接并在短时间内再次询问。当您不想让服务器打开大量长时间运行的空闲连接时,这很有用,但这意味着您将只能以轮询间隔的速度接收新消息,并且会产生建立一个每次轮询时都有新的 HTTP 连接。 AJAX 长轮询:连接到服务器并保持连接打开,直到有新消息可用。这使您可以快速传递新消息并减少 HTTP 连接频率,但会导致服务器上出现更多长时间运行的空闲进程。 iframe 长轮询:与上面相同,只是使用隐藏的 iframe 而不是 XHR 对象。当您想要进行跨站点长轮询时,对于绕过同源策略很有用。 插件:Flash 的 XMLSocket、Java 小程序等可用于为浏览器建立更接近于真正低级持久套接字的东西。HTML5 套接字并没有真正改变可用的底层策略。大多数情况下,它们只是将已经使用的策略形式化,并允许明确识别持久连接,从而更智能地处理。假设您想向移动浏览器发送基于 Web 的推送消息。使用正常的长轮询,移动设备需要保持清醒以保持连接。使用 WebSockets,当移动设备想要进入睡眠状态时,它可以将连接交给代理,当代理接收到新数据时,它可以唤醒设备并传回消息。
服务器端是敞开的。要实现短轮询应用程序的服务器端,您只需要某种按时间顺序排列的消息队列。当客户端连接时,他们可以将新消息移出队列,或者他们可以传递一个偏移量并读取任何比其偏移量新的消息。
实施服务器端长轮询是您的选择开始缩小的地方。大多数 HTTP 服务器都是为短期请求而设计的:连接、请求资源,然后断开连接。如果 300 人在 10 分钟内访问您的网站,并且每个人需要 2 秒来连接和下载 HTTP 资源,那么您的服务器在任何给定时间平均会打开 1 个 HTTP 连接。使用长轮询应用程序,您会突然保持 300 倍的连接数。
如果您运行自己的专用服务器,您或许可以处理此问题,但在共享托管平台上,您可能会遇到资源限制,App Engine 也不例外。 App Engine 旨在处理大量低延迟请求,例如短轮询。您可以在 App Engine 上实现长轮询,但这是不明智的;运行时间超过 30 秒的请求将被终止,长时间运行的进程会耗尽您的 CPU 配额。
App Engine 的解决方案是即将推出的 Channel API。通道 API 使用 Google 现有的强大 XMPP 基础架构实现长轮询。
Brett Bavar and Moishe Lettvin's Google I/O talk 的使用模式如下:
App Engine 应用在远程服务器上创建一个频道,并返回一个频道 ID,并将其传递给网络浏览器。
class MainPage(webapp.RequestHandler):
def get(self):
id = channel.create_channel(key)
self.response.out.write(
'channel_id': id)
网络浏览器通过 iframe 长轮询将频道 ID 传递给同一个远程服务器以建立连接:
<script src='/_ah/channel/jsapi'></script>
<script>
var channelID = ' channel_id ';
var channel =
new goog.appengine.Channel(channelId);
var socket = channel.open();
socket.onmessage = function(evt)
alert(evt.data);
</script>
当发生有趣的事情时,App Engine 应用可以向用户的频道推送消息,浏览器的长轮询请求会立即收到:
class OtherPage(webapp.RequestHandler):
def get(self):
# something happened
channel.send_message(key, 'bar')
【讨论】:
【参考方案2】:例如,Jetty 从版本 7 开始支持此功能:Jetty Websocket Server
Google App Engine 也有这方面的计划。他们甚至在 Google I/O 2010 上对此进行了演示,但尚未投入生产。见ticket #377
【讨论】:
以上是关于http 服务器将如何处理 html5 网络套接字?的主要内容,如果未能解决你的问题,请参考以下文章
当循环中调用了异步函数时,Node.JS 将如何处理循环控制?
5 月 1 日之后,我们将如何处理 jcenter() 存储库以及它的替代方案是啥?