java - http 服务器将如何处理 html5 网络套接字?

标签 java google-app-engine html webserver websocket

我阅读了很多关于 HTML5 的文章,我特别喜欢网络套接字,因为它们促进了网络服务器和网络浏览器之间的双向通信。

但我们一直在阅读有关 chrome、opera、firefox、safari 为 html5 做准备的信息。哪个网络服务器准备好使用网络套接字功能?我的意思是,Web 服务器是否能够在今天启动后续通信? Google 自己的 Appengine 怎么样?

如何在 Java 中编写利用此功能的示例 Web 应用程序?

最佳答案

网络服务器和浏览器之间的双向通信并不是什么新鲜事。如果您正在阅读的问题有新答案发布,Stack Overflow 今天就会这样做。使用现有技术实现套接字式行为有几种不同的策略:

  • AJAX 短轮询:连接到服务器并询问是否有任何新消息。如果没有,请立即断开连接并在短时间间隔后再次询问。当您不想为服务器保留大量长时间运行的空闲连接时,这很有用,但这意味着您只会以与轮询间隔一样快的速度接收新消息,并且会产生建立每次轮询时新的 HTTP 连接。
  • AJAX 长轮询:连接到服务器并保持连接打开,直到有新消息可用。这使您可以快速传递新消息并降低 HTTP 连接的频率,但会导致服务器上出现更多长时间运行的空闲进程。
  • iframe 长轮询:与上面相同,只是使用隐藏的 iframe 而不是 XHR 对象。当您想进行跨站点长轮询时,对于绕过同源策略很有用。
  • 插件:Flash 的 XMLSocket、Java applet 等可用于为浏览器建立更接近于真正的低级持久套接字的东西。

HTML5 套接字并没有真正改变可用的底层策略。大多数情况下,它们只是将已经在使用的策略形式化,并允许持久连接被明确识别,从而更智能地处理。假设您想向移动浏览器发送基于 Web 的推送消息。对于正常的长轮询,移动设备需要保持清醒以保持连接。使用 WebSockets,当移动设备想要进入 hibernate 状态时,它可以将连接移交给代理,当代理接收到新数据时,它可以唤醒设备并传回消息。

服务器端是完全开放的。要实现短轮询应用程序的服务器端,您只需要某种按时间顺序排列的消息队列。当客户端连接时,它们可以将新消息移出队列,或者它们可以传递一个偏移量并读取比它们的偏移量更新的任何消息。

实现服务器端长轮询是您开始缩小选择范围的地方。大多数 HTTP 服务器都是为短期请求而设计的:连接、请求资源,然后断开连接。如果 300 人在 10 分钟内访问您的站点,并且每个人需要 2 秒来连接和下载 HTTP 资源,则您的服务器在任何给定时间平均会打开 1 个 HTTP 连接。使用长轮询应用程序,您突然需要保持 300 倍的连接数。

如果您运行的是自己的专用服务器,您或许能够处理这个问题,但在共享托管平台上,您可能会遇到资源限制,App Engine 也不异常(exception)。 App Engine 旨在处理大量低延迟请求,例如短轮询。您可以在 App Engine 上实现长轮询,但这是不明智的;运行时间超过 30 秒的请求将被终止,长时间运行的进程将耗尽您的 CPU 配额。

App Engine 的解决方案是即将推出的 Channel API。 channel API 使用 Google 现有的强大 XMPP 基础架构实现长轮询。

Brett Bavar and Moishe Lettvin's Google I/O talk列出使用模式如下:

App Engine 应用程序在远程服务器上创建一个 channel ,并返回一个 channel ID,并将其传递给网络浏览器。

class MainPage(webapp.RequestHandler):

    def get(self):
        id = channel.create_channel(key)
        self.response.out.write(
            {'channel_id': id})

Web 浏览器通过 iframe 长轮询将 channel 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 应用程序可以向用户的 channel 推送一条消息,浏览器的长轮询请求将立即收到它:

class OtherPage(webapp.RequestHandler):

    def get(self):
        # something happened
        channel.send_message(key, 'bar')

关于java - http 服务器将如何处理 html5 网络套接字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3202188/

相关文章:

java - 如何从 Google App Engine 数据存储区 (Java) 正确检索 int?

jQuery .data() 不适用于 $(this)

java - 在java结构中搜索数值

java - Sonar 构建失败,显示项目 xxxxx : sonar. 配置文件设置为 'YYYY',但与任何语言的任何配置文件都不匹配

java - 从 Spring Security 访问 Spring MVC 服务

html - 与边距和 img 大小相关的 Firefox 特定 CSS 错误

javascript - Jquery 移动到其他 div(动画)

java - Windows 上的 Ant 编码问题 - UTF-8 文件但在变音符号上吐出垃圾

python - 没有 Web 服务的 Bigquery cron 作业

java - 通过 http 监视文本文件的更改