美文网首页Ruby On Railsruby on railsRuby
ruby on rails中sidekiq的使用

ruby on rails中sidekiq的使用

作者: 小新是个程序媛 | 来源:发表于2018-04-18 20:44 被阅读1822次

    sidekiq使用redis来保存所有的job和操作数据,所以sidekiq依赖于redis,并且sidekiq默认会去连位于localhost:6379的redis服务器,但是生产环境中可能需要自定义地址

    前提:安装并启动redis,不同机器对应的安装方式可自行百度,mac下安装redis可通过

    brew install redis
    

    1. 配置redis

    配置sidekiq所依赖的redis位置,必须同时定义sidekiq的server和client
    config/initializers/sidekiq.rb

    # 这里的地址和端口号(1643)都需要配置成正确的
    Sidekiq.configure_server do |config|
      config.redis = { url: 'redis://redis.wdxtub.com:1643/12' } #标准格式 config.redis = { url: "redis://#{redis_server}:#{redis_port}/#{redis_db_num}", namespace: redis_namespace }
    end
    Sidekiq.configure_client do |config|
      config.redis = { url: 'redis://redis.wdxtub.com:1643/12' } #标准格式 config.redis = { url: "redis://#{redis_server}:#{redis_port}/#{redis_db_num}", namespace: redis_namespace }
    end
    

    如果要使用 UNIX socket,URL 应该类似于 unix://#{Rails.root}/tmp/sockets/redis.sock

    2. 配置文件

    配置config/sidekiq.yml文件,一般只有在需要配置高级选项的时候才需要配置这个文件(如果不使用这个名字,可以使用-c指定 sidekiq -c config/name.yml)

    :verbose: false
    :concurrency: 5 # 并发数
    :pidfile: ./tmp/pids/sidekiq.pid
    :logfile: ./log/sidekiq.log # 输出的日志地址
    :timeout: 30
    :queues:
      - default # 写在队列参数中的, 表示让 sidekiq 处理这个 queue
      - [HardWorker, 2] # 使用数组的形式写, 第一个参数为打开的 queue 的名称, 第二个为优先级
      - [EmailWorker, 3]
      - [PasswordWorker, 4]
    
    development:
    :concurrency: 5
    staging:
    :concurrency: 10
    production:
    :concurrency: 5
    

    3. gemfile中添加对应的包

    gem 'sidekiq', '4.0.1', :require => false
    

    4. 在app/jobs文件下新建一个job,来处理异步请求(可以使用命令也可以手动创建)

    rails g job add_lots_of_users
    #rails g sidekiq:worker Hard # will create app/workers/hard_worker.rb #在app/workers文件下新建一个worker,来处理异步请求(可以使用命令也可以手动创建)
    

    文件中会生成如下内容

    class AddLotsOfUsersJob < ActiveJob::Base
      queue_as :default
    
      def perform(*args)
        # Do something later
      end
    end
    
    #class HardWorker
      #include Sidekiq::Worker
      #def perform(name, count)
        # do something
      #end
    #end
    

    将耗时的程序写到perform里

    def perform(*args)
     # Do something later
     sleep 10
     1000.times do |index|
       user = User.new
       user.name = "atpking#{index}"
       user.save
     end
    end
    

    5. 在需要的地方controller或者model中调用,调用示例如下

    注意:perform是一个实例方法,但是在调用的时候是用类调用

    AddLotsOfUsersJob.perform_later #常规异步执行
    AddLotsOfUsersJob.set( wait: 20.minutes ).perform_later #指定延迟多久执行
    @users = User.all
    #HardWorker.perform_async('bob', 5) #常规异步执行
    #HardWorker.perform_in(5.minutes, 'bob', 5) #延迟执行
    #User.delay.do_some_stuff(current_user.id, 20) # 也可以通过 delay 来新建任务
    

    6. 在config/application.rb中指定active_job的adapter

    adapter默认使用的adapter是Active Job Inline需要指定为sidekiq才支持异步(如果是使用worker这一步可以省略)

    config.active_job.queue_adapter = :sidekiq
    

    7. 在rails项目的根目录启动sidekiq

    bundle exec sidekiq -d -C config/sidekiq.yml #-d是指后台运行 -c指定配置文件,默认sidekiq.yml文件
    

    另外由于sidekiq的进程并不是非常稳定,可定会自己断掉,所以可以配合监控工具Monit(可以监控任何进程,只需要设定启动和重开的方式即可)使用,详情还请自行百度

    8. sidekiq web可视化(这个步骤是可选的)

    1. 添加gem

    gemfile添加sinatra

    gem 'sinatra', '2.0.0.beta2',require: false
    

    执行

    bundle install
    

    tips:
    之前直接添加gem 'sinatra'运行时导致报错,google之后判断可能是由于sinatra gem的版本问题,导致运行时报错,修正后的sinatra gem 的为gem 'sinatra', '2.0.0.beta2',require: false

    error
    1. 设置路由

    routes.rb添加

      require 'sidekiq/web'
      mount Sidekiq::Web => '/sidekiq'
    
    1. 打开sidekiq web页面

    打开Sidekiq web界面,检查该作业是否被处理,浏览器中输入

    #port为项目实际启动的端口号
    http://localhost:port/sidekiq
    
    sidekiq web页面

    为了使Sidekiq有更好的体验需要遵循的一些原则

    (以下纯属翻译)

    1.让每个 job 的参数小而简单

    从前面我们知道,Sidekiq 会把 perform_async 函数的参数保存在 Redis 中,而常见的错误做法是这样的:
    quote = Quote.find(quote_id)
    SomeWorker.perform_async(quote)
    这有什么问题呢?问题很大!把整个 quote 对象都保存在 Redis 中了,而且由于操作是通过异步队列来完成的,很可能在执行到这句话时,quote 本身都改变了,所以我们尽可能让每个 job 的参数小而简单,比方说可以改成像这样
    SomeWorker.perform_async(quote_id)
    另外除了数据本身可能改变这个问题外,还有序列化和反序列化的问题。Sidekiq 使用 JSON.dump 和 JSON.load 来完成存取操作,所以如果不是简单的 JSON 数据类型,在这一步很可能出错。

    2.让每个 job 满足幂等性和事务性

    幂等性保证了任务可以执行很多次,不会出现结果不一致的情况;事务性则是保证了结果不因为在 job 执行半路出现问题。我们唯一能做的假设是 Sidekiq 至少会执行每个 job 一次。

    3.拥抱并发

    Sidekiq 是为并发设计的,所以在设计任务时一定要以并发的想法去思考。如果 Sidekiq 占用流量太高的话,可以考虑用连接池来限制连接数量。

    注:本文讲的是Sidekiq结合ActiveJob使用的方式,也可以单独使用Sidekiq Worker
    文章中注释掉的是单独使用Sidekiq Worker创建任务跟使用ActiveJob的不同部分

    参考
    https://github.com/mperham/sidekiq/wiki/Getting-Started
    (worker)
    https://ihower.tw/rails/background-process.html
    (active_job)

    相关文章

      网友评论

        本文标题:ruby on rails中sidekiq的使用

        本文链接:https://www.haomeiwen.com/subject/uhmbkftx.html