Ошибки Mongoid/Moped при обработке заданий с Sidekiq

Я вижу сбой тонны заданий при запуске Sidekiq, которые связаны с проблемами соединения с моей базой данных Mongo. Я испытываю стресс-тестирование машины с большой нагрузкой, поэтому я поставил в очередь более 18 000 заданий, каждое из которых повторялось 5 секунд после сбоя. Некоторые из заданий (я полагаю, что с работником, который смог успешно получить поток соединения) сработали просто отлично. Тогда у меня есть куча других с ошибками вроде этого:

2013-12-26T19:25:35Z 13447 TID-m2biw WARN: {"retry"=>true, "queue"=>"default",
"class"=>"ParseFileWorker", "args"=>[{"filename"=>"/opt/media/AE-67452_36.XML"}], 
"jid"=>"5d6c48fa94ed8c8da1b226fc", "enqueued_at"=>1388084903.6113343, 
"error_message"=>"Could not connect to a primary node for replica set #
<Moped::Cluster:44552140 @seeds=[<Moped::Node resolved_address=\"127.0.0.1:27017\">]>", 
"error_class"=>"Moped::Errors::ConnectionFailure", "failed_at"=>"2013-12-26T19:16:25Z", 
"retry_count"=>3, "retried_at"=>2013-12-26 19:25:35 UTC}

Есть также ошибки тайм-аута, такие как следующие:

Timeout::Error: Waited 0.5 sec

Обратите внимание, что я запускаю Rails 4 с кодом Mongoid, извлеченным из основной ветки в https://github.com/mongoid/mongoid. Из того, что я читал, в предыдущих версиях Mongoid требовалось явное закрытие соединений, когда выполнялась работа Sidekiq. Mongoid 4 должен делать это автоматически. Я не могу подтвердить, делает ли он это или нет. Кажется, что проблема в два раза, когда задания ставятся в очередь, слишком быстрое соединение недоступно или время ожидания истекло. Некоторые работники успешно открывают связь. Некоторые задания приходится ждать до повторной попытки разбора.

Я не совсем уверен, что лучшее решение здесь. Если я медленно ставлю работу в очередь, все работает нормально. К сожалению, это не так, как приложение будет работать в реальном мире.

Как я могу обеспечить, чтобы мои задания sidekiq получили соединение Moped/Mongoid, необходимое для выполнения работы, или подождать, пока одно из них не станет доступным для обработки? Видя тонну исключений / ошибок из-за этой проблемы. Ниже приведена трассировка стека распространенной повторяющейся ошибки:

2013-12-26T20:56:58Z 1317 TID-i70ms ParseFileWorker JID-0fc375d8fd9707e7d3ec3238 INFO: fail: 1.507 sec
2013-12-26T20:56:58Z 1317 TID-i70ms WARN: {"retry"=>true, "queue"=>"default", "class"=>"ParseFileWorker", "args"=>[{"filename"=>"/opt/media/AC-19269_287.XML"}], "jid"=>"0fc375d8fd9707e7d3ec3238", "enqueued_at"=>1388091410.0421875, "error_message"=>"Waited 0.5 sec", "error_class"=>"Timeout::Error", "failed_at"=>2013-12-26 20:56:58 UTC, "retry_count"=>0}
2013-12-26T20:56:58Z 1317 TID-i70ms WARN: Waited 0.5 sec
2013-12-26T20:56:58Z 1317 TID-i70ms WARN: /media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/connection_pool-1.2.0/lib/connection_pool/timed_stack.rb:35:in `block (2 levels) in pop'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/connection_pool-1.2.0/lib/connection_pool/timed_stack.rb:31:in `loop'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/connection_pool-1.2.0/lib/connection_pool/timed_stack.rb:31:in `block in pop'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/connection_pool-1.2.0/lib/connection_pool/timed_stack.rb:30:in `synchronize'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/connection_pool-1.2.0/lib/connection_pool/timed_stack.rb:30:in `pop'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/connection_pool-1.2.0/lib/connection_pool.rb:66:in `checkout'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/connection_pool-1.2.0/lib/connection_pool.rb:53:in `with'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/node.rb:114:in `connection'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/node.rb:141:in `disconnect'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/node.rb:156:in `down!'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/node.rb:442:in `rescue in refresh'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/node.rb:431:in `refresh'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/cluster.rb:182:in `block in refresh'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/cluster.rb:194:in `each'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/cluster.rb:194:in `refresh'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/cluster.rb:151:in `nodes'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/cluster.rb:240:in `with_primary'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/read_preference/primary.rb:55:in `block in with_node'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/read_preference/selectable.rb:65:in `call'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/read_preference/selectable.rb:65:in `with_retry'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/read_preference/primary.rb:54:in `with_node'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/gems/moped-2.0.0.beta4/lib/moped/query.rb:127:in `first'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/bundler/gems/mongoid-fc589421bf8b/lib/mongoid/contextual/mongo.rb:201:in `block (2 levels) in first'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/bundler/gems/mongoid-fc589421bf8b/lib/mongoid/contextual/mongo.rb:537:in `with_sorting'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/bundler/gems/mongoid-fc589421bf8b/lib/mongoid/contextual/mongo.rb:200:in `block in first'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/bundler/gems/mongoid-fc589421bf8b/lib/mongoid/contextual/mongo.rb:449:in `try_cache'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/bundler/gems/mongoid-fc589421bf8b/lib/mongoid/contextual/mongo.rb:199:in `first'
/media/apps/tsn-parser-server/vendor/bundle/ruby/2.0.0/bundler/gems/mongoid-fc589421bf8b/lib/mongoid/contextual.rb:19:in `first'
/media/apps/tsn-parser-server/app/models/parser/core.rb:88:in `prepare_parse'

** ОБНОВИТЬ **

Если я уменьшу количество работников sidekiq до 10 или около того, проблема перестанет возникать - просто потому, что меньше работников, открывающих соединение с MongoDB, когда работает только 10 потоков. Должен быть способ использовать пул соединений для Mongoid/Moped в sidekiq. Поскольку Rails отвечает за настройку и разрыв соединения, я не уверен, как это сделать.

** ОБНОВЛЕНИЕ 2 **

Когда я указываю это на наш производственный сервер, это становится в 10 раз хуже. Почти каждый поток Timeout::Error, Некоторые проходят, но совсем не многие. Это довольно ужасно. По крайней мере, проблему можно "обойти", ограничив sidekiq 10 работниками, если MongoDB локальный. Но это нереальный вариант использования, и мне нужно иметь возможность подключаться к базе данных на отдельном компьютере.

1 ответ

Решение

Первое, что нужно проверить, будет mongod ограничение соединения и ограничения ОС на стороне БД, так как они были хорошими, казалось вероятным, что размер пула соединений мог быть ограничивающим фактором.

Оказывается, размер пула соединений mongoid по умолчанию был 5, что довольно мало для вашего большого числа работников. Повышение их, как показано в примере здесь, позволит большему количеству работников одновременно получать соединение.

Другие вопросы по тегам