现在的位置: 首页 > 综合 > 正文

sidekiq在 Plain Ruby 项目中的使用

2018年02月11日 ⁄ 综合 ⁄ 共 2207字 ⁄ 字号 评论关闭

在高并发的场景下,使用异步队列可以解决慢io阻塞的问题,当用户请求到达时,先把消息塞在队列中,然后快速返回, 后台任务再从队列中取出消息慢慢处理。 sidekiq 就是一个用ruby实现的,底层使用redis,的一个异步队列。 

在rails工程中, 请参考 https://github.com/mperham/sidekiq/wiki/Getting-Started   很详细, 在这不过多讨论。 

Goliath 是一个高效的ruby web框架,在 rest full的接口场景下,既能满足效率的要求(上千请求每秒),又开发简单, (建议使用1.0.4版本, 1.0.3版本有一个crash的bug,需要打补丁)。 在这我们来讨论 goliath 这种纯ruby的环境下 sidekiq的使用问题。 

sidekiq的 examples 目录下有一个 por.rb  的文件, 这个就是纯ruby环境下 sidekiq的队列。 

require 'sidekiq'

Sidekiq.configure_client do |config|
  config.redis = { :namespace => 'x', :size => 1 }
end

Sidekiq.configure_server do |config|
  config.redis = { :namespace => 'x' }
end

class PlainOldRuby
  include Sidekiq::Worker
  def perform(how_hard="super hard", how_long=1)
    puts "Workin' #{how_hard}"
  end
end

启动命令  

# RACK_ENV=production bundle exec sidekiq -r ./por.rb -d -L log/sidekiq.log  -c 10  

-c 参数可以指定在一个进程中开启多少个并发, 在任务重的情况下可以考虑多开几个, (但要注意 并发数要小于 数据库连接池的连接数量,否则会导致数据库连接失败,应为并发多,db的连接数不够用)

在goliath代码中, 比如 webapi.rb 中 

class Webapi < Goliath::API
  def response(env)
    path = env[Goliath::Request::REQUEST_PATH]
    case path
    when /^\/webapi\/weixin\//  
      PlainOldRubyWorker.perform_async("test")    #  收到用户的请求,然后异步调用,把消息 塞到 sidekiq的异步队列中
    end 
    [200,{},""] 
  end 
end


以上代码是最常见的使用场景, 但有一个问题,随着por中 class 越来越多,sidekiq的并发数量上升, class 任务之间会产生干扰, 一旦某个任务存在性能问题,会导致并发资源都被占用,所以需要一种资源隔离的策略, 重要的任务单独创建一个sidekiq进程。 

对上面的por.rb 文件做改造 

class NotifyWorker
  include Sidekiq::Worker
  sidekiq_options queue: :notify_worker, retry: 3, backtrace: true    #  这 指定队列的 名称, 重试次数 

  def perform( openid, msg , msgdata={})
    ...
    logger.info "-->send to #{openid} ,  #{succ}"
  end
end

启动命令    -q  参数,当前进程的工作队列,这样就与其他队列隔离开了。 

# RACK_ENV=production bundle exec sidekiq -r ./por.rb -d -L log/sidekiq.log -c 4 -q  notify_worker

注意 por.rb  修改后,  sidekiq 进程 和 goliath进程都需要重启才能生效。 

测试结果如下 :

启动2个 sidekiq  分别指定不同的队列参数 ;

RACK_ENV=production bundle exec sidekiq -r ./por.rb -d -L log/sidekiq.log -c 1 -q  callback_worker
RACK_ENV=production bundle exec sidekiq -r ./por.rb -d -L log/sidekiq.log -c 2 -q  notify_worker

root     23881  0.0  3.0 753132 62644 ?        Sl   16:51   0:02 sidekiq 2.17.1 [0 of 1 busy]

root     23997  0.1  3.3 822924 67788 ?        Sl   16:52   0:02 sidekiq 2.17.1 [0 of 2 busy]

监控 sidekiq的日志输出 

在进程 23881 上处理  callback_worker 任务 

2014-08-12T09:37:06Z 23881 TID-ovw9yoy70 EventCallbackWorker JID-ce334f112b6374b8fc47cde1 INFO: start

在进程 23997 上处理 notify队列相关的任务 

2014-08-12T09:37:07Z 23997 TID-owpks93e0 NotifyWorker JID-b0239ffa243b559dfba1be18 INFO: start

以上,可以达到隔离sidekiq任务的方法。  

抱歉!评论已关闭.