五问Sidekiq # W11

Sidekiq 是Ruby社区最受欢迎的异步任务框架之一,几乎是Rails项目标配。

本文,我将从实际使用者的角度来提出疑问,通过一一解答这些问题来剖析Sidekiq是如何工作的。(代码基于Sidekiq-5.1.3)

在Web请求中,有很多任务是可以放到后台执行的,比如用户购买商品付款成功后,就可以直接向用户购买成功,相应的短信发送,物流通知等等就可以放到后台任务去做,不用在用户购买的同时立即执行,这些任务也称作异步任务。在Rails中,使用Sidekiq是这样的:

class HardWorker
  include Sidekiq::Worker
  sidekiq_options :retry => 5, queue: 'hard'
  def perform(name)
    # do something
  end
end
HardWorker.perform_async('bob')     # 异步执行任务

我们通常使用上面的方式,注册一个任务,让它异步执行。那么本文的第一个问题来了:

1. 上面的这条代码 HardWorker.perform_async('bob')  到底做了什么

很容易看出这个类方法定义在 Sidekiq::Worker 里面,在源码中找到相关的代码:

  def perform_async(*args)
    client_push('class' => self, 'args' => args)
  end
  def client_push(item) # :nodoc:
    pool = Thread.current[:sidekiq_via_pool] || get_sidekiq_options['pool'] || Sidekiq.redis_pool
    # 有省略
    Sidekiq::Client.new(pool).push(item)
  end

可以看出,把自己的Class和方法的参数生成了一个hash,传递进了client_push方法, pool是一个redis连接, 调用了Client的实例方法, 通过一层层代码的查看,最终来到了我们最值得关注的一个方法:

    def atomic_push(conn, payloads)
      if payloads.first['at']  # 延时任务,例如指定了一分钟之后才执行
        conn.zadd('schedule', payloads.map do |hash|
          at = hash.delete('at').to_s
          [at, Sidekiq.dump_json(hash)]
        end)
      else
        q = payloads.first['queue']
        now = Time.now.to_f
        to_push = payloads.map do |entry|
          entry['enqueued_at'] = now
          Sidekiq.dump_json(entry)
        end
        conn.sadd('queues', q)
        conn.lpush("queue:#{q}", to_push)  #重点
      end
    end

payloads是通过上面item参数加工后得到的,里面除了之前的class,args参数之外,还会有sidekiq_options方法定制的部分参数,例如queue。 我们重新专注于上面的代码,第一个问题的答案已经很明显了。

从上面可以清晰的看出,异步执行相关的数据被打包成json,然后使用redis的lpush命令塞进了一个队列中,这个队列的名字和指定的queue有关系,按照我们上面的配置,这个队列的就是 "queue:hard"。写入队列的数据大概像这样:

{'class' => MyWorker, 'args' => [1, 2, 3]}

通过这些参数,就可以知道需要被执行的是哪个Worker,并且参数是什么。 注册异步任务到此就结束了,第二个问题随之来了。

2. 上面这些队列里的数据是怎么被消费的

通过第一个问题,我们知道了,

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值