有两个 Rails 项目,爬虫 和 展示,他们共享一个 redis 服务器,爬虫的 sidekiq 配置的默认 redis_db 是 1,展示的 sidekiq 配置的默认 redis_db 是 2。 希望做到当爬虫爬到一个网页后,通知展示项目去跑一个 ReadCrawlerJob 的任务。
有一种做法是在展示中起一个 循环监听,来监听爬虫的 redis 中的一个 list,爬虫每次爬到东西就往 list 里面加。
我希望能把这个过程整合到 sidekiq 里面去,而不用去维护多余的进程,所以想出了下面的办法,测试暂时 OK,不知道会有什么潜在的问题。
1.在 initialize 中 monkey patch 一下 Sidekiq ::Client,参照 sidekiq 在 github 上最新的代码,用 new 取代了 default
class Sidekiq::Client
class << self
def default
new
end
end
end
2.配置一个指向 展示 redis_db 的 redis connection_pool
$show_redis_pool = ConnectionPool.new { Redis.new({db: 2}) }
3.在爬虫里面写一个空的 ReadCrawlerJob,类名和队列名要和 展示项目中一致。在 展示 里面实现有功能 ReadCrawlerJob, 并开启 sidekiq。
# 爬虫
class ReadCrawlerJob < ActiveJob::Base
queue_as :read_crawler_job
def perform(data)
# 这里啥也不做
end
end
# 展示
class ReadCrawlerJob < ActiveJob::Base
queue_as :read_crawler_job
def perform(data)
# 这里实现功能
end
end
4.在爬虫抓到一个网页后
old = Thread.current[:sidekiq_via_pool]
Thread.current[:sidekiq_via_pool] = $show_redis_pool
ReadCrawlerJob.perform_later(data)
Thread.current[:sidekiq_via_pool] = old
这样,在爬虫抓到内容后,会向 redis_db 2 的 queue 添加 job,展示项目就可以自动处理了。