前文研究过利用 Flash XMLSocket 作即时通讯的 Juggernaut,虽然它可以简易的做到即时通讯,但使用非 HTTP 通讯和非开放标准这两点很让人在意,有满有其他的解决方案?
ActiveMQ 的 AJAX Client
在思考的过程中,发觉我想做的不正是使用消息通讯的软件吗?这类软件己经有一个很好的 Model:Messaging Oriented Middleware(MOM)。接着我跑到 Apache ActiveMQ 的网站研究有没有可用的方案。果然,在 AMQ 的源码中就有一个 AJAX 的 messaging client。
ActiveMQ 是开源的 JMS 专案,技术成熟而且被很多其他产品应用。它的 AJAX Client 利用连接 Server 上的 Messaging Servlet ,由Servlet 再向 AMQ 发送讯息。等等,AJAX 的 A 不就是非同步的意思吗?怎样用 AJAX 做到即时通讯?答案是结合 Poll 和 AJAX。Browser 首先用 AJAX 连接到 Servlet (Poll) ,如果有讯息就会即时把讯息返回,如果没有讯息就会让 client 等待,直到指定的时限(约30秒、比一般 browser 和 socket 的 timeout 短 )。每个 AJAX request 完结后 client 会立即重试,这样 client 便可以得到有如 push 的效果了。比起一般 Server Push 的 Comet ,这种做法更符合一般 HTTP 的 Request - Response 模式,由于与普通 HTTP 无异,一般的 Firewall 和 Browser 也支援。
在 Rails 中的 AJAX Poll
ActiveMQ 的方法虽好,但它是一个 Servlet ,我们难道要另架一台 Java Application Server?就算不介意架这台 Server ,还要用 proxy 之类的方法解决 AJAX 不能 Cross-Domain 的问题。有没有方法只用 Rails 就做到这种 AJAX Poll 的效果?
答案是 No and Yes。用普通的方法 Rails 不能做到以上效果。Rails 是一个单线程的环境 ,也就是说全部 Request 也由同一支 Thread 控制。在以上情境中“叫 Client 在 Request 中等待直至有信息”等于叫整个 server 停下来。幸好,Rails 单线程不等于 Server 也必须单线程。Adam的 Comet with Rails + Mongrel http://adam.blogs.bitscribe.net/2007/05/08/comet-with-rails-mongrel/ 中示范了怎样用自订 HttpHandler 让 Rails 可以持续地跟 Client 连接。我们可以在 Browser 呼叫 AJAX,在 Mongrel 的 HttpHandler 中把这些 Request 转成向 MOM 的呼叫,把消息化为 HTTP Response 送回 browser,如下图。

理论差不多了,看看怎样实作吧!
在 Rails 和 Mongrel 作即时股票报价软件
ActiveMQ 的 Web Demo 包括一个股票报价软件。它分成 Consumer 和 Producer 两部份,Consumer 是收取服价资料的 Client ,Producer 则是发报股价的 Server。我们的目标就是要在 Rails 实作这个软件。
1. 环境设定
这个 project 使用 Apache ActiveMQ 作 MOM,使用 Mongrel 作 Rails Server,使用 Stomp 连接这两者。安装 AMQ 很容易,只需去它的下载网站下载就行了,解压后在 AMQ 的 folder 输入以下指令可以启动 AMQ:
- ./bin/activemq
接着我们安装 Mongrel 和 Stomp:
- gem install mongrel
- gem install stomp
当然我们需要一个 Rails project
- rails Messaging
准备工作完成,可以写程式了!
2. Producer - 股票报价的消息源
首先我们作一个 Controller "portfolio" 给这个 project,我们分别用 producer 和 index 两个 action 代表 Producer 和 Consumer。
- cd Messaging

