简体   繁体   English

Redis、Sidekiq 和 Heroku 应用程序

[英]Redis, Sidekiq and Heroku Apps

I have two Rails Apps that need to share some state.我有两个 Rails 应用程序需要共享一些 state。 Each App needs to run background jobs during their execution lifetimes.每个应用程序都需要在其执行生命周期内运行后台作业。 I added Heroku Redis to each App, and Sidekiq.我将 Heroku Redis 添加到每个应用程序和 Sidekiq。 So when I run background jobs, everything is great.所以当我运行后台作业时,一切都很好。

I do not have shared state until I point one App's REDIS_URL at the other Apps REDIS_URL and then both Apps are using the same shared Redis instance, I assume, and hence I have some shared state.我没有共享 state,直到我将一个应用程序的 REDIS_URL 指向另一个应用程序 REDIS_URL,然后两个应用程序都使用相同的共享 Redis 实例,我假设,因此我有一些共享的 Z9ED39E2EA631586B3EZEF98。

Now both Sidekiq instances share the same Redis, and one App is seeing the other Apps jobs and puking, because it has no idea about the other Apps jobs.现在两个 Sidekiq 实例共享相同的 Redis,并且一个应用程序正在查看其他应用程序的作业并呕吐,因为它不知道其他应用程序的作业。

What is a clearer way of sharing state and keeping the jobs separate like they should be?共享 state 并保持工作分开的更清晰方法是什么? I guess I need to just buy a cache I can use as shared state separate from the jobs?我想我只需要购买一个可以用作共享 state 的缓存,与工作分开吗?

Heroku App 1. Owns Redis Instance. Heroku 应用程序 1. 拥有 Redis 实例。 Has Sidekiq.有 Sidekiq。 Runs Job AaaBbbJob Heroku App 2. Points at Redis Instance from App1.运行作业 AaaBbbJob Heroku App 2。从 App1 指向 Redis 实例。 Has Sidekiq有 Sidekiq

I notice the logs for App 2 show job AaaBbbJob tried running and failed as AaaBbbJob was not found.我注意到 App 2 的日志显示作业 AaaBbbJob 尝试运行并失败,因为未找到 AaaBbbJob。

In the logs of App 1, Job AaaBbbJob ran fine...在 App 1 的日志中,Job AaaBbbJob 运行良好......

So my confusion lies in trying to assure myself that this is all OK.所以我的困惑在于试图向自己保证这一切都很好。 When App 1 through a job via Sidekiq into Redis, for whatever reason, App 2 saw that job in Redis too, and tried to run it.当应用程序 1 通过 Sidekiq 通过作业进入 Redis 时,无论出于何种原因,应用程序 2 在 Redis 中也看到了该作业,并尝试运行它。

So my question is, since throwing Jobs into Redis is now shared between two Apps, they both try and run ANY jobs they see?所以我的问题是,由于将作业放入 Redis 现在在两个应用程序之间共享,它们都尝试运行他们看到的任何作业?

You have two problems here:你在这里有两个问题:

  • 2 different apps use Sidekiq and share the same Redis instance 2 个不同的应用程序使用 Sidekiq 并共享相同的 Redis 实例
  • need to exchange data between two apps需要在两个应用程序之间交换数据

For the first question, your 2 apps may have different Sidekiq Jobs but because of the same Redis instance, each of the Background app (which runs respective apps slug) pick all Sidekiq Jobs and only understand the jobs that they know about.对于第一个问题,您的 2 个应用程序可能有不同的 Sidekiq 作业,但由于相同的 Redis 实例,每个后台应用程序(运行各自的应用程序 slug)都会选择所有 Sidekiq 作业,并且只了解他们知道的作业。

You can't really help as Sidekiq is done like this.因为 Sidekiq 就是这样完成的,所以你真的帮不上忙。 It is a feature that allows to run multiple dynos with Sidekiq for the same app.这是一项允许使用 Sidekiq 为同一应用程序运行多个测功机的功能。

What you can do to separate the two types of Sidekiq jobs is to assign a redis Database to each app: What's the Point of Multiple Redis Databases?您可以做些什么来区分这两种类型的 Sidekiq 作业是为每个应用程序分配一个 redis 数据库: 多个 Redis 数据库有什么意义?

Redis can segregate data into 16 different databases. Redis 可以将数据隔离到 16 个不同的数据库中。

For example my Redis config in one of my app is:例如,我的一个应用程序中的 Redis 配置是:

config/redis.yml配置/redis.yml

development:
  url: redis://localhost:6379/
  db: 2  

production:
  url: <%= ENV["REDIS_URL"] %>
  db: 2

test: 
  url: redis://localhost:6379/
  db: 2 

In another app I am using the database number 1. Then there is no collision.在另一个应用程序中,我使用的是 1 号数据库。然后没有冲突。

The matching Sidekiq initializer looks like this then:匹配的 Sidekiq 初始化程序如下所示:

conf = Rails.application.config_for(:redis)
confid = conf.merge({id: "Sidekiq-server-PID-#{::Process.pid}"})
confservid = conf.merge({id: "Sidekiq-server"})

if Rails.env.production?

  Sidekiq.configure_client do |config|    
    config.redis = conf    
  end

  Sidekiq.configure_server do |config|    
    config.redis = conf    
  end

end


if Rails.env.development?
  Sidekiq.configure_client do |config|         
    config.redis = confid    
  end

  Sidekiq.configure_server do |config|    
    config.redis = confservid        
  end

end

As you can see I am naming all redis clients (in development) on top of what I have explained.如您所见,在我解释的内容之上,我将所有 redis 客户端(正在开发中)命名。 It is very useful to understand Redis clients consumption.了解 Redis 客户端的消耗非常有用。

Regarding your second question: sharing "app state" I think it is about sharing global values such as constants or class variables.关于您的第二个问题:共享“应用程序状态”我认为这是关于共享全局值,例如常量或 class 变量。

It is probably possible to share this data through Redis but this is definitely ugly.可能可以通过 Redis 共享此数据,但这绝对是丑陋的。 You turn 2 apps a single monolith.您将 2 个应用程序变成了一个整体。 Even if you manage to do it properly, you have to rewrite everything when you want each app to have its own Redis instance.即使您设法正确执行此操作,当您希望每个应用程序拥有自己的 Redis 实例时,您也必须重写所有内容。

The only way to do this is through a controller behaving as an API that would answer requests and deliver data to the other app.做到这一点的唯一方法是通过 controller 表现为 API 将响应请求并将数据传递到其他应用程序。

Each app will need a Redis connection pool for the other Redis instance.每个应用程序都需要一个 Redis 连接池用于其他Redis 实例。 Then App A can use those connections to send data or jobs to App B or push jobs to its sidekiq.然后 App A 可以使用这些连接将数据或作业发送到 App B 或将作业推送到其 sidekiq。 Using multiple Redises is known as sharding.使用多个 Redis 被称为分片。

https://github.com/mperham/sidekiq/wiki/Sharding https://github.com/mperham/sidekiq/wiki/Sharding

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM