BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

Rails ActiveMessaging入门

| 作者 Andrew Kuklewicz 关注 0 他的粉丝 ,译者 罗小平 关注 0 他的粉丝 发布于 2007年5月5日. 估计阅读时间: 20 分钟 | Google、Facebook、Pinterest、阿里、腾讯 等顶尖技术团队的上百个可供参考的架构实例!

前言

Rails已在数据库驱动型Web应用领域站稳脚跟。而集成了消息处理的插件式框架——ActiveMessaging,更扩大了Rails的应用范围。利用ActiveMessaging和Rails,我们可以轻松集成全异系统(如MQ消息发送模块、J2EE Web应用和后台常驻任务等),或创建事件和消息驱动型架构。有人这样总结过:ActiveMessaging就像ActiveRecord为数据库所做的一切那样,正为消息处理而努力。本文将介绍ActiveMessaging、与其相关的技术,以及在Rails中的使用方法。

消息处理标准与代理

实现消息处理,首先需要三个方面的支持:通讯协议、协议服务端代理、协议客户端库。从技术角度而言,剩下的工作就是开发一个实现消息发送和接收的系统了。在本文的例子中,我们将把服务端和客户端合二为一,放在同一个程序中。ActiveMessaging支持Stomp协议。这是一个通过无线连接,使用TCP/IP,实现文本型消息流式传输的协议标准。其设计理念要求尽可能将协议简化,以求无论利用哪种语言开发客户端或服务端,都能相当轻松(比如Ruby Stomp客户端代码,连带注释和空行,总行数仅约400)。因此,它几乎可以集成任何系统。

Apache ActiveMQ消息代理缺省支持Stomp,当然也可以使用其他代理,而且选择是越来越多。比如最近公布的StompConnect项目,计划向绝大多数开源消息处理类产品开放Stomp和ActiveMessaging,并实现任何JMS代理到Stomp代理的转换。在客户端,ActiveMessaging支持基于适配器模式(Adapter Pattern)的协议,就Stomp而言,它使用在Stomp RubyGem基础上扩展而成的适配器。未来可能支持的适配器更多,但目前只有Stomp。

本文中,我们使用还未正式发布的ActiveMQ4.2代理。ActiveMQ在所有平台上都有安装说明;如果你有Java1.4或更高版本,那么可以简化安装过程:

cd /usr/local/src
#unix and cygwin
wget http://people.apache.org/repo/m2-snapshot-repository/org/apache/activemq/apache-activemq/4.2-SNAPSHOT/apache-activemq-4.2-20070221.081507-10-src.tar.gz
#os x
curl -O http://people.apache.org/repo/m2-snapshot-repository/org/apache/activemq/apache-activemq/4.2-SNAPSHOT/apache-activemq-4.2-20070221.081507-10-src.tar.gz

cd ..
tar xvfz apache-activemq-4.2-20070221.081507-10-src.tar.gz
cd apache-activemq-4.2-incubator-SNAPSHOT
./bin/activemq

这就OK了!缺省情况下,ActiveMQ对Stomp的支持会自动配置完成;若自动配置不成功,你可以在conf/activemq.xml中添加如下设置:

<transportConnectors> 
...
<!-- Add this line -->
<transportConnector name="stomp" uri="stomp://localhost:61613"/>
</transportConnectors>

以上是ActiveMQ所需的最小化配置。更详细的情况可以参考ActiveMessaging的ActiveMQ维客,以及ActiveMQ用户手册

Rails的配置

Rails 1.1和MySql准备就绪后,还需要安装两个工具:daemonsStomp

sudo gem install daemons
sudo gem install stomp

现在让我们新建一个Rails工程“MessageMonster”以及对应数据库,最后安装ActiveMessaging插件。

cd /usr/local/dev
rails MessageMonster
mysqladmin create messagemonster_development -u root
cd MessageMonster
script/plugin install http://activemessaging.googlecode.com/svn/trunk/plugins/activemessaging

所有准备工作就绪,现在可以写程序了。

消息处理

首先需要创建“处理器”,用ActiveMessaging的术语来说,就是一个支持消息目标者有序接收和处理消息的类。它在设计模型中是必不可少,相当于消息驱动的控制器,代码量也占最大比例。

如你所愿,处理器可以自动生成:

script/generate processor PersistMessage 

第一次运行“generate”,会输出如下结果:

create  app/processors
create app/processors/persist_message_processor.rb
create config/messaging.rb
create config/broker.yml
create app/processors/application.rb
create script/poller

下面,我们具体讨论上述各行输出结果的含义。
  • app/processors:全部处理器所在目录。
  • app/processors/persist_message_processor.rb:按缺省配置生成的新处理器。
  • app/processors/application.rb:供新处理器继承的通用超类。它实现了一些通用功能,如错误处理。
  • config/broker.yml:代理配置,指明了连接消息代理的方法。类似database.yml,但它是用于消息代理的。
  • config/messaging.rb:消息传输用到的其他配置,如目的地、消息头。
  • script/poller:ActiveMessaging用以监听消息的后台程序。后文对此还有说明。

首先考察broker.yml,注意各项参数,确保代理配置正确:

development:
adapter: stomp
login: ""
passcode: ""
host: localhost
port: 61613
reliable: true
reconnectDelay: 5
...

以上只包括了ActiveMQ的缺省配置项。如果是正式发布的产品,远程运行代理,则还需要增加访问用户和密码项。

接下来再看看persist_message_processor.rb:

class PersistMessageProcessor < ApplicationProcessor
subscribes_to :persist_message
def on_message(message)
logger.debug "PersistMessageProcessor received: " + message
end
end

上述代码实现了:persist_message消息的订阅,并指定了方法on_message。当:persist_message消息到来时,ActiveMessaging将回调on_message。参数message负责按字符串格式传递消息内容;依靠@message,还可以直接访问Stomp消息对象。通过再次调用subscribes_to,处理器可以订阅更多消息。

:persist_message是处理器订阅的目标消息的逻辑名。在config/messaging.rb中定义目标消息:

ActiveMessaging::Gateway.define do |s|
s.queue :persist_message, '/queue/PersistMessage'
end

messaging.rb类似于Rails中的routes.rb。它主要实现逻辑名(:persist_message)到代理(/queue/PersistMessage)中目标消息的映射。当然还有很多其他配置项,但就本例而言,自动生成的缺省配置已经足够了。

接下来,我们要告知处理器预先存储消息以供处理,如下创建一个消息模型:

script/generate model message 

现在,用如下两行代码更新db/migrate/001_create_messages.rb:

create_table :messages do |t|
t.column :body, :text
t.column :received_date, :datetime
end

调用migrate创建该数据表:

rake db:migrate 

接下来修改处理器的on_message方法,这将使用到新的消息模型:

def on_message(message)
logger.debug "PersistMessageProcessor received: " + message
my_message = Message.create(:body=>message, :received_date=>DateTime.new)
end

看到这里,我们仔细想想会发现,其实没有什么新东西,和在Rails控制器中编码完成相同功能的过程差不多。因此使用ActiveMessaging时,Rails应用环境的所有便利性都可供利用。

处理器一旦捕获消息,就可将它抛出(像瓶装后逐个抛售那样)等待处理。

发送消息

发送消息时,我们会在同一个应用程序中用到Rails视图和控制器:

script/generate controller SendMessage index

编辑视图,提交消息文本,显示预先持久化的消息的可更新列表:

 style="color: green">

 

 

Send Message >Message
                                                    

编辑控制器,发送消息。ActiveMessaging包含一个提供消息简单发布方法的小型类MessageSender,利用它可从任何类轻松实现消息发送。publishes_to定义了消息接收者,但除了验证config/messaging.rb中所配置目标者的有效性,不干别的事。如下是控制器使用这些方法的过程:

require 'activemessaging/processor'

class SendMessageController < ApplicationController

include ActiveMessaging::MessageSender
publishes_to :persist_message

def index
@messages = Message.find :all
end

def new
@message = params[:message]
publish :persist_message, @message
flash[:notice] = "'#{@message}' sent"
@messages = Message.find :all
render :action => 'index'
end
end

至此,大功告成。控制器将在用户提交时发出消息,当你下次浏览或者刷新此页面时,将看到被处理器保存的消息。

例子运行

ActiveMessaging在独立进程中运行,由script/poller控制。因此仅仅启动Rails服务器,是无法接收到消息的。运行这个例子,我们总共需要启动三个进程:ActiveMQ代理、Rails服务器(发送消息)和script/poller(接收消息)——每个进程都是系统的独立节点。

启动ActiveMQ:

cd /usr/local/apache-activemq-4.2-incubator-SNAPSHOT
./bin/activemq

启动Rails:

cd /usr/local/dev/MessageMonster
script/server

启动ActiveMessaging:

cd /usr/local/dev/MessageMonster
script/poller run

script/poller遵循后台程序的运行规则。处理让进程保持运转的“run”参数外,还可以传递“start”、“stop”、“restart”和“status”。另外,为提高消息处理效率,也能同时运行多个进程实例。

现在,打开测试页面(如http://localhost:3000/send_message),输入消息吧,比如经典的“Hello World”。消息送达时,你应该在poller窗口看到如下信息:

Loading /usr/local/dev/MessageMonster/app/processors/application.rb
Loading /usr/local/dev/MessageMonster/app/processors/persist_message_processor.rb
=> Subscribing to /queue/PersistMessage (processed by PersistMessageProcessor)
=> All subscribed, now polling
PersistMessageProcessor received: Hello World

poller总会显示启动时加载的处理器,以及代理上的订阅请求。如果代理不可用或不存在,系统会根据broker.yml的配置尝试别的代理。另外,你还能在poller中看到ActiveMessaging处理器接收的、来自于Rails的消息。而且,如果你使用“Refresh List”功能,将会在Rails视图中看到被ActiveMessaging处理器持久化的消息。

结束语

希望你能喜欢这篇介绍ActiveMessaging的文章,相信你已经感觉到了它的潜力和易用性。其实,ActiveMessaging还有很多本文没有提及的高级功能,如优化的异常处理、多poller运行群组处理器,以及异步消息中Stomp和ActiveMQ消息头的处理方法、JMS集成和可选订阅等。是不是相当惊讶呢,现在不会认为ActiveMessaging无法满足你的需要了吧!

  • 若要了解更多信息,我推荐你细读ActiveMessaging站点,尤其是其中的维客源代码
  • 我们还在继续改进ActiveMessaging,欢迎你参加我们的讨论,多提意见和建议

    查看英文原文:Introduction to ActiveMessaging for Rails
    作者简介:Andrew Kuklewicz,具有10年软件开发经验,PRX(Public Radio Exchange,提供电台内容分发、同行评审和许可的免费服务)的资深Web开发师。业余时间,他是Ruby Stomp项目成员和ActiveMessaging的当前维护者,同时还是Ruby On Rails、Plone和Java等开源项目的活跃分子。

    译者简介:罗小平,上海某大型公司互联网中心技术总监,CSDN大版主,网络ID为lxpbuaa(桂枝香在故国晚秋),曾著有《Delphi精要》一书。个人博客为http://blog.csdn.net/lxpbuaa,现在CSDN主持翻译国外专家Herb Sutter的中文博客。他的Email和MSN为lxpbuaa AT 263.net

  • 评价本文

    专业度
    风格

    您好,朋友!

    您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

    获得来自InfoQ的更多体验。

    告诉我们您的想法

    允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

    当有人回复此评论时请E-mail通知我

    感谢Jeffp捧场宣传啊 by zhang snow

    第一次录制screencast,难免有点紧张,还请大家海涵。多提建议吧大家!

    Re: 感谢Jeffp捧场宣传啊 by meng joe

    不错,顶顶!snow zhang,可不可以加我下?我msn:joe_meng2000@hotmail.com

    允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

    当有人回复此评论时请E-mail通知我

    允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

    当有人回复此评论时请E-mail通知我

    2 讨论

    登陆InfoQ,与你最关心的话题互动。


    找回密码....

    Follow

    关注你最喜爱的话题和作者

    快速浏览网站内你所感兴趣话题的精选内容。

    Like

    内容自由定制

    选择想要阅读的主题和喜爱的作者定制自己的新闻源。

    Notifications

    获取更新

    设置通知机制以获取内容更新对您而言是否重要

    BT