Приложение Rails: переподключить джаггернаут redis после разветвления?

Я работаю над приложением Rails, которое использует Juggernaut для передачи данных клиентам через регулярные промежутки времени. Я использую действие контроллера, чтобы начать толкание; но так как продвижение часто является долгим процессом (10 минут или более), я использую spawn для форка задачи. Например:

def start_pushing
  spawn_block(:argv => "juggernaut-pushing") do
    for x in y
      Juggernaut.publish(stuff in here)
      sleep(30) # delay before publishing next item
    end
  end
end

Проблема в том, что я нахожу эту ошибку в файле журнала, когда нажимаю на действие start_pushing:

spawn> Exception in child[27898] - Redis::InheritedError: Tried to use a connection from a child process without reconnecting. You need to reconnect to Redis after forking.

Поэтому я добавил следующее прямо в spawn_block, надеясь, что это решит проблему:

    require 'redis'
    $redis.client.disconnect
    $redis = Redis.new(:host => 'localhost', :port => 6379)

Похоже, это не исправить, хотя действие работало с перерывами, даже до того, как я добавил это для сброса $ redis. Я думаю, что, возможно, сброс $ redis ничего не делает; Джаггернаут все еще получает доступ к старому соединению. Это кажется вероятным? Как я могу убедиться, что Джаггернаут использует новое соединение Redis?

Пожалуйста, дайте мне знать о любых вопросах о том, что я описываю. Я ценю помощь, потому что я застрял прямо сейчас.

1 ответ

Проблема заключается в использовании global (переменная, которая начинается с $) и использовании Passenger. Все глобальные данные распределяются между ВСЕМИ пассажирскими процессами. Redis имеет своего рода проверку, чтобы убедиться, что идентификатор процесса вызова Redis совпадает с идентификатором, который подключен. Таким образом, если redis был подключен с использованием пассажира 1, но затем работник 2 использует его, он выдаст эту ошибку.

См. Метод connect и sure_connected класса Redis::Client для получения дополнительной информации.

Решение объясняется в этом вопросе. По сути, они предполагают, что вам нравится memcache, как описано здесь.

Короче говоря, в вашем config / environement.rb добавьте следующее:

if defined?(PhusionPassenger)
    PhusionPassenger.on_event(:starting_worker_process) do |forked|
        if forked
            # We're in smart spawning mode.
            $redis.reconnect
        else
            # We're in conservative spawning mode. We don't need to do anything.
        end
    end
end
Другие вопросы по тегам