案例研究:Stream Congress 的实时更新

发布于 2023-10-16 11:11:05 字数 6287 浏览 28 评论 0

通过 WebSockets EventSource ,HTML5 使开发人员能够构建与服务器实时通信的 Web 应用程序。 Stream Congress (可在 Chrome 网上应用店 中找到)提供有关美国国会运作的实时更新。它流式传输来自众议院和参议院的地板更新,相关新闻更新,国会议员的推文以及其他社交媒体更新。该应用程序旨在全天保持开放状态,因为它捕获了国会的业务。

从 WebSockets 开始

WebSockets 规范因其支持的功能而受到相当多的关注: 浏览器和服务器之间的稳定,双向 TCP 套接字 。TCP 套接字上没有强加任何数据格式;开发人员可以自由定义消息传递协议。实际上,将 JSON 对象作为字符串传递是最方便的。用于侦听实时更新的客户端 JavaScript 代码干净而简单:

var liveSocket = new WebSocket("ws://streamcongress.com:8080/live");
liveSocket.onmessage = function(payload) {
  addToStream(JSON.parse(payload.data).reverse());
};

虽然浏览器对 WebSockets 的支持很简单,但服务器端支持仍处于形成阶段。 Socket.IO on Node.js 提供了最成熟、最强大的服务器端解决方案之一。像 Node.js 这样的事件驱动服务器非常适合 WebSockets。对于替代实现,Python 开发人员可以使用 Twisted Tornado ,而 Ruby 开发人员则拥有 EventMachine

Cramp 简介

Cramp 是一个异步的 Ruby Web 框架,运行在 EventMachine 之上。它是由 Ruby on Rails 核心团队的成员 Pratik Naik 编写的。Cramp 为实时 Web 应用程序提供简单的领域特定语言 (DSL),是 Ruby Web 开发人员的理想选择。那些熟悉在 Ruby on Rails 中编写控制器的人会认识到 Cramp 的风格:

require "rubygems"
require "bundler"
Bundler.require
require 'cramp'
require 'http_router'
require 'active_support/json'
require 'thin'

Cramp::Websocket.backend = :thin

class LiveSocket < Cramp::Websocket
   periodic_timer :check_activities, :every => 15

   def check_activities
     @latest_activity ||= nil
     new_activities = find_activities_since(@latest_activity)
     @latest_activity = new_activities.first unless new_activities.empty?
     render new_activities.to_json
   end
 end

routes = HttpRouter.new do
  add('/live').to(LiveSocket)
end
run routes

由于 Cramp 位于非阻塞事件机器之上,因此需要牢记以下几个注意事项:

  • 必须使用非阻塞数据库驱动程序,如 MySQLPlus em-mongo
  • 必须使用事件驱动的 Web 服务器。内置了 对薄和 and 彩虹 的支持。
  • Cramp 应用程序必须与支持 Stream Congress 的主 Rails 应用程序分开运行,重新启动并独立监控。

当前限制

WebSockets 在 2010 年 12 月 8 日遭遇挫折,当时一个安全漏洞被公布。 Firefox 和 Opera 都删除了浏览器对 WebSockets 的支持。虽然不存在纯 JavaScript polyfill,但 有一个 Flash 回退 已经被广泛采用。然而,依赖 Flash 远非理想。尽管 Chrome 和 Safari 继续支持 WebSockets,但很明显,要在不依赖 Flash 的情况下支持所有现代浏览器,WebSockets 需要被替换。

回滚到 AJAX 轮询

决定从 WebSockets 移回“老派”AJAX 轮询。虽然从磁盘和网络 I/O 的角度来看效率要低得多,但 AJAX 轮询简化了 Stream Congress 的技术实现。最重要的是,消除了对单独的 Cramp 应用程序的需求。AJAX 端点由 Rails 应用程序提供。客户端代码已修改为支持 jQuery AJAX 轮询:

var fillStream = function(mostRecentActivity) {
  $.getJSON(requestURL, function(data) {
    addToStream(data.reverse());
    setTimeout(function() {fillStream(recentActivities.last());}, 15000);
  });
};

但是,AJAX 轮询并非没有缺点。依赖 HTTP 请求/响应周期意味着即使没有任何新更新,服务器也能看到恒定负载。当然,AJAX 轮询并没有利用 HTML5 所提供的优势。

EventSource:适合的工具

到目前为止,关于 Stream Congress 的性质忽略了一个关键因素:应用程序只需要单向流式传输更新,从服务器到客户端 - 下游。它不需要是实时的上游客户端到服务器的通信。

从这个意义上说,WebSockets 对于 Stream Congress 来说是矫枉过正的。服务器到客户端的通信是如此普遍,以至于它被赋予了一个通用术语:推送。事实上,许多现有的 WebSocket 解决方案,从托管的 PusherApp 到 Rails 库 Socky ,都针对推送进行了优化,并且根本不支持客户端到服务器的通信。

输入事件源,也称为服务器发送的事件。该规范在上下文中与 WebSocket 相比具有优势,服务器到客户端推送:

  • 浏览器端有一个类似的、简单的 JavaScript API。
  • 打开的连接是基于 HTTP 的,不会下降到低级别的 TCP。
  • 连接关闭时自动重新连接。

Going Back to Cramp

最近几个月,Cramp 增加了对 EventSource 的支持。该代码与 WebSockets 实现非常相似:

class LiveEvents < Cramp::Action
  self.transport = :sse

  periodic_timer :latest, :every => 15

  def latest
    @latest_activity ||= nil
    new_activities = find_activities_since(@latest_activity)
    @latest_activity = new_activities.first unless new_activities.empty?
    render new_activities.to_json
  end
end

routes = HttpRouter.new do
  add('/').to(LiveEvents)
end
run routes

使用事件源时要记住的一个重要问题是不允许跨域连接。这意味着 Cramp 应用程序必须从与主 Rails 应用程序相同的 streamcongress.com 域提供服务。这可以通过 Web 服务器上的代理来实现。假设 Cramp 应用程序由 Thin 提供支持并在端口 8000 上运行,则 Apache 配置如下所示:

LoadModule  proxy_module         /usr/lib/apache2/modules/mod_proxy.so
LoadModule  proxy_http_module    /usr/lib/apache2/modules/mod_proxy_http.so
LoadModule  proxy_balancer_module    /usr/lib/apache2/modules/mod_proxy_balancer.so

<VirtualHost *:80>
  ServerName streamcongress.com
  DocumentRoot /projects/streamcongress/www/current/public
  RailsEnv production
  RackEnv production
  <Directory /projects/streamcongress/www/current/public>
    Order allow,deny
    Allow from all
    Options -MultiViews
  </Directory>

  <Proxy    balancer://thin>
    BalancerMember    http://localhost:8000   
  </Proxy>
  ProxyPass /live    balancer://thin/   
  ProxyPassReverse /live    balancer://thin/   
  ProxyPreserveHost on

</VirtualHost>

此配置将事件源终结点设置为 streamcongress.com/live .

Stable Polyfill

与 WebSockets 相比,EventSource 最显着的优势之一是回退完全基于 JavaScript,不依赖于 Flash。Remy Sharp 的 polyfill 通过在原生不支持 EventSource 的浏览器中实现长轮询来实现这一点。因此,EventSource 今天可以在所有启用了 JavaScript 的现代浏览器上运行。

结论

HTML5 为许多新的和令人兴奋的 Web 开发可能性打开了大门。借助 WebSockets 和 EventSource,Web 开发人员现在拥有干净、定义明确的标准来支持实时 Web 应用程序。但并非所有用户都运行现代浏览器。选择实现这些技术时,必须考虑正常降级。WebSockets 和 EventSource 的服务器端工具仍处于早期阶段。在开发实时 HTML5 应用时,请务必牢记这些因素。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

0 文章
0 评论
904 人气
更多

推荐作者

玍銹的英雄夢

文章 0 评论 0

我不会写诗

文章 0 评论 0

十六岁半

文章 0 评论 0

浸婚纱

文章 0 评论 0

qq_kJ6XkX

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文