Rails 想使用 rails 做一个常在线的 gtalk 机器人, 如何让这个机器人 run 起来?

ruohanc · 2012年10月19日 · 最后由 ruohanc 回复于 2012年10月20日 · 4348 次阅读

说的就是我以前做好的贴吧追小说机器人, 项目在 github 上 .

我现在想把他在 rails 下重新实现一遍 (其实暂时并没有打算做页面, 只是为了借用 rails 完整的工具来部署). 然后我就不知道如何才能让这个机器人一直 run 在线了.

原本的做法是写一个 sidekiq.rb, 然后在这个文件里面 require 需要的库, 然后用全局变量 $bot hold 住一个 xmpp 连接. 之后的发送消息什么的操作都通过这个全局变量来做.

我现在觉得使用全局变量并不是一个合适的方法, 但是除此之外我还真不知道怎么样才能正确的 hold 住这个连接了. 请教各位.

只是想保持长链接?那直接跑个脚本就可以了吧,为什么需要 sidekiq ?

PS: 我之前参与开发的一个 Gem https://github.com/yong/purple_ruby,是对 libpurple 的封装,可以用来比较方便的写 Bot

try daemon?

匿名 #5 · 2012年10月19日

try delayed_job ?

#5 楼 @help5305fff #4 楼 @leekelby #3 楼 @chentianwen

hi, 谢谢你们的回复, 看来我没描述清楚我的意思. 我写代码的时间不长, 却有点代码洁癖. 我不希望像以前那样用一个全局变量保存这个 bot 的连接, 然后在程序的另外地方需要调用这个 bot 的时候再去操作这个全局变量. 我希望能有一种看起来更安全更合理, 也更漂亮的方式来实现.

现在有的想法大约是写一个单例类, 然后让这个类的类变量 hold 住这个连接, 然后每次发信息都操作这个类. 但这样似乎也会把这个类搞的很大, 并且跟其他的类耦合 (因为其他的类要调用类似 Bot::im_send 的方法). 而且我对 rails 不熟悉. 不清楚这样的代码应该放在哪个文件夹下才合适 (这个类似乎跟 mvc 都无关) 是不是应该放在 vender/plugins 下面?

匿名 #7 · 2012年10月19日

其实放 model 里也可以 放 lib 下也可以 放 config/initializers 下也可以

#7 楼 @help5305fff 肉眼观察之后觉得 config/initializers 更像样一点 ^^.

#6 楼 @ruohanc 套用电信系统分析的名词,你要做的功能属于能力层,而 rails 是业务层系统框架,所以才会觉得适配有困难 直接用 ruby 做 bot 功能吧,然后分析一下管控方面的需求,暴露出接口,最后,如果需要,可以将这个接口用 rails/sinatra 包装为 web based

匿名 #10 · 2012年10月19日

放 model,一般我定义为业务类 放 lib,我一般定义公共类 放 config/initializers,我一般定义初始化类

#2 楼 @yedingding 粗略的看了你那个 gem. 赞一个 (没想到你还会 C 啊). 不过这并不能解决我的问题. 这只是一个用于连接 IM 服务器的 gem (当然看起来比我现在用的 xmpp4r 要给力一点, 反正我也在重构, 会试一试这个的)

#9 楼 @fsword 嗯. 你说的对, 这样设计确实不合适. 我原本以为用 resque 这样的队列可以合理的搞定这个问题.

那再问一下对暴露接口有什么建议么. 暴露 web 接口? 还是 socket 接口? 暴露这两种接口都用什么 gem 合适呢?

直接 dbus 调 telepathy 就好了

#12 楼 @ruohanc 我了解的 gem 不多,不好给建议。不过这个接口是面向对象中的含义,只要一致就行了,其它不重要,你之前的想法(放到 initializers)也不矛盾,关键要实用

举个例子,最简单的场景是你只关心这个机器人会 crash,那只要一个状态查询和重启服务即可,可以把代码包装成一个 Worker 类,内部是独立线程,提供启动/重启/查询状态的方法,这就是你的接口。

class Worker
  def start; ... end
  def stop;  ... end
  def status; ... end
end

接下来可能是两种做法

  • 一种是基于 web 的,可以用 rails(只能是单进程单线程工作方式),在 initializers 里启动这个 worker,通过 controller 查询工作状态和启动/重启
  • 另外一种更加简化,命令行 nohup 启动一下这个 Worker.rb 即可,启动代码类似这样: ```ruby # run.rb require './worker.rb' require 'logger'

LOGGER = Logger.new 'work.log' begin Worker.new.start rescue LOGGER.error 'fail' end

这种情况下,关键是故障告警,可以让nginx直接输出work.log文件,然后用监控宝监控这个url的内容即可

#12 楼 @ruohanc Bot 启动的时候开一个 socket 监听,然后所有事情都通过 socket 通讯,也就是用 server 和 client 来解耦

#15 楼 @yedingding 那要怎么做才能让这个 bot 跟 rails 一起启动呢.?

#16 楼 @ruohanc 这得看你 Rails 是怎么启动的。我更倾向于单独启动,比如我之前就是用 monit 来专门管理 Rails 和 IM 机器人这个进程的

#16 楼 @ruohanc 你能说明一下你想通过 rails 提供什么服务吗?如果只是启动和关闭机器人,那么这个 rails 没必要

#18 楼 @fsword 嗯..我只是很懒. 想借用 rails 的一些工具. 比如像 db:migrate, 还有 active_record, 还有像 production, development, testing 使用不同数据库等功能. 虽然我在这之前的版本用 sequel 作为 ORM 实现了这些功能, 但是感觉太折腾. 而单独把这些工具拿出来用又比较麻烦 (我还是初心者, 对于我来说可能先简单的实现功能比较重要), 所以现在想用 rails 来简化开发, 同时简化部署

#19 楼 @ruohanc 那就把你的 robot 包装好接口,然后在 initializer 里面启动

其实直接使用 AR 和环境变量也不复杂

gem 'mysql2'
require 'active_record'
require 'yaml'

MYAPP_ENV=ENV['MYAPP_ENV']

ActiveRecord::Base.establish_connection YAML.load( File.read 'config/config.yml' )[MYAPP_ENV]

$: << './lib/tieba_xiaoshuo_bot/models'
require 'users'
...

至于 db migrate,我估计你也不奢望能回滚吧,那就每次升级写一个数据迁移脚本完事

#20 楼 @fsword 赞...

#2 楼 @yedingding 你这个 gem 真不错! 不过好像没文档? 我只能看 purple_ruby.c 瞎猜?

#21 楼 @ruohanc API 本身没什么吧 去看 xmpp 协议就行了

#22 楼 @doitian 似乎完全不是一回事. 这个 purple_ruby 是 pidgin 的通信库 libpurple 的 ruby 包装. 方法定义似乎就是这一段: Github.com

@yedingding 我似乎没有找到获取在线 (或者所有) 用户的方法啊.?

#20 楼 @fsword hey, 我发现在 initializer 里面启动这个 bot 挺合适的, 但是主题代码写在那里似乎并不好. 怎么办呢.

#2 楼 @yedingding 虽然这个库很牛逼. 不过它对 pidgin 的依赖会导致无法在云平台上部署吧.?

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册