Приложение 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