浩文 联系 关于本站 登录 注册

中间件

commit信息:Updated Middleware (markdown) | 提交者:kevjin | 提交时间:2020-02-25 | 版本:c646c65

Sidekiq有着与Rack相似的中间件理念:少量代码即可实现功能。Sidekiq将中间件分为客户端和服务端。

  • 客户端中间件 在将作业推送到Redis之前运行,并且让你在它被推送之前 修改/停止 该作业。
  • 服务端中间件 ‘围绕着’作业处理运行。

定制中间件

Sidekiq 5+发表时没有中间件。许多gems和服务要安装中间件来跟踪作业或提供额外的功能。你也可以添加自己的中间件。

客户端中间件

在把作业推送到Redis之前,你可以使用客户端中间件给它添加作业元数据。如果你需要设置一些全局状态像 当前区域、在multi-tenant应用中的当前tenant等等,在作业被执行之前,相同的作业数据可以被服务端中间件使用。

客户端中间件可以接收类参数作为类对象,或者包含类名的字符串。

不调用 yield 或者不返回 job 以外的任何内容,这样将不会导致进一步的中间件被调用,并且该作业将不会被推送到队列。 (请注意,yield 将返回跟 job 相同的值)

module MyMiddleware
  module Client
    class CustomerJobAttribute
      # @param [String, Class] worker_class the string or class of the worker class being enqueued
      # @param [Hash] job the full job payload
      #   * @see https://github.com/mperham/sidekiq/wiki/Job-Format
      # @param [String] queue the name of the queue the job was pulled from
      # @param [ConnectionPool] redis_pool the redis pool
      # @return [Hash, FalseClass, nil] if false or nil is returned,
      #   the job is not to be enqueued into redis, otherwise the block's
      #   return value is returned
      # @yield the next middleware in the chain or the enqueuing of the job
      def call(worker_class, job, queue, redis_pool)
        # return false/nil to stop the job from going to redis
        return false if queue != 'default'
        job['customer'] = Customer.current_id
        yield
      end
    end
  end
end

服务端中间件

你可以使用服务端中间件在作业执行期间做一些工作。以下是一个记录任何作业的所有异常的例子。

不调用 yield 将导致不再有任何中间件被调用,并且该作业的perform方法将不被调用。

class MyMiddleware::Server::ErrorLogger
  # @param [Object] worker the worker instance
  # @param [Hash] job the full job payload
  #   * @see https://github.com/mperham/sidekiq/wiki/Job-Format
  # @param [String] queue the name of the queue the job was pulled from
  # @yield the next middleware in the chain or worker `perform` method
  # @return [Void]
  def call(worker, job, queue)
    begin
      yield
    rescue => ex
      puts ex.message
    end
  end
end

在你注册一个中间件时,你也可以给该中间件的初始化器传递一些选项:

class MyMiddleware::Server::ErrorLogger
  def initialize(options=nil)
    # options == { :foo => 1, :bar => 2 }
  end
  def call(worker, msg, queue)
    begin
      yield
    rescue => ex
      puts ex.message
    end
  end
end

注册中间件

把你的中间件注册为链的一部分:

Sidekiq.configure_client do |config|
  config.client_middleware do |chain|
    chain.add MyMiddleware::Client::CustomerJobAttribute
  end
end

Sidekiq.configure_server do |config|
  config.server_middleware do |chain|
    chain.add MyMiddleware::Server::ErrorLogger, :foo => 1, :bar => 2
  end
end

我建议把这些代码放到你Rails应用的config/initializers/sidekiq.rb文件中。

在两个地方都注册了客户端中间件

这些运行在Sidekiq服务中的作业,它们可以像客户端一样,自己推送新的作业给Sidekiq。在那种情况下,你必须在configure_server块中配置你的客户端中间件。

Sidekiq.configure_client do |config|
  config.client_middleware do |chain|
    chain.add MyMiddleware::Client::CustomerJobAttribute
  end
end

Sidekiq.configure_server do |config|
  config.client_middleware do |chain|
    chain.add MyMiddleware::Client::CustomerJobAttribute
  end
  config.server_middleware do |chain|
    chain.add MyMiddleware::Server::ErrorLogger, :foo => 1, :bar => 2
  end
end

移除中间件

如果由于一些原因你需要移除一个中间件,你可以像下面这样写配置文件:

Sidekiq.configure_server do |config|
  config.server_middleware do |chain|
    chain.remove Some::Middleware
  end
end

中间件排序

使用-v选项启动Sidekiq时会打印配置了的客户端和服务端中间件链。如果多个中间件可能以某种方式发生冲突,排序就显得至关重要。

上一篇: API 下一篇: 兼容Resque