Большое количество тем под единорогом

Я занимаюсь отладкой некоторых утечек соединения Posgtres в нашем приложении. Несколько дней назад мы внезапно пересекли 100 соединений, хотя этого быть не должно, потому что у нас всего 8 рабочих-единорогов и процесс sidekiq (25 потоков).

Сегодня я просматривал htop и увидел, что мои рабочие-единороги порождают массу потоков. Например:

введите здесь описание изображения Я правильно понял? Этого не должно быть, верно? Если это порождаемые потоки, есть идеи, как это отлаживать?

Спасибо! Кстати, моя другая проблема - (соединения Postgres) Отладка утечки соединения unicorn postgres

ИЗМЕНИТЬ

Я просто следовал некоторым советам здесь - http://varaneckas.com/blog/ruby-tracing-threads-unicorn/ — и когда я напечатал трассировку стека из рабочих потоков, вот что я получил, когда потоков много..

[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `pop'
[17176] /u/apps/eventstream_production/shared/bundle/ruby/2.2.0/gems/eventmachine-1.0.8/lib/eventmachine.rb:1057:in `block in spawn_threadpool'
[17176] ---
[17176] -------------------

Это мой unicorn.rb https://gist.github.com/steverob/b83e41bb49d78f9aa32f79136df5af5f и он порождает поток для EventMachine в after_fork.

Причина для EventMachine заключается в следующем --> https://github.com/keenlabs/keen-gem#asynchronous-publishing

Это нормально? Разве темы не должны быть убиты? Может ли это также вызывать открытие ненужных соединений с базой данных? Спасибо

ОБНОВЛЕНИЕ: я только что узнал, что использую более старую версию драгоценного камня PubNub, который использует EM, и я столкнулся с этими строками в файле pubnub.log:

D, [2016-04-06T21:31:12.130123 #1573] DEBUG -- pubnub: Created event Pubnub::Publish
D, [2016-04-06T21:31:12.130144 #1573] DEBUG -- pubnub: Pubnub::SingleEvent#fire
D, [2016-04-06T21:31:12.130162 #1573] DEBUG -- pubnub: Pubnub::SingleEvent#fire | Adding event to async_events
D, [2016-04-06T21:31:12.130178 #1573] DEBUG -- pubnub: Pubnub::SingleEvent#fire | Starting railgun
D, [2016-04-06T21:31:12.130194 #1573] DEBUG -- pubnub: Pubnub::Client#start_event_machine | starting EM in new thread
D, [2016-04-06T21:31:12.130243 #1573] DEBUG -- pubnub: Pubnub::Client#start_event_machine | We aren't running on thin
D, [2016-04-06T21:31:12.130264 #1573] DEBUG -- pubnub: Pubnub::Client#start_event_machine | EM already running

person Steve Robinson    schedule 08.04.2016    source источник
comment
Я тоже не считаю это нормальным. Может быть, вы используете Threads в коде своего приложения? Не могли бы вы попробовать использовать процедуру, описанную здесь, чтобы получить трассировку стека из unicorn threads (особенно см. раздел Что Ruby делает в данный момент?)? Таким образом, вы можете найти, где задерживаются нити.   -  person BoraMa    schedule 08.04.2016
comment
Вот это да. спасибо за эту ссылку @BoraMa   -  person Steve Robinson    schedule 08.04.2016
comment
Я предполагаю, что вы настроили reaper_frequency в своем database.yml так, чтобы средний поток был Reaper thread и я думаю, что это нормально. Надо подождать, пока нити соберутся...   -  person BoraMa    schedule 08.04.2016
comment
@BoraMa Ааа, хорошо, хорошо. :) Обновлено с выводами.   -  person Steve Robinson    schedule 09.04.2016


Ответы (2)


Так что, в конце концов, поведение кажется нормальным в вашем конкретном случае.

Предоставленные вами трассировки стека потоков единорога (полученные с помощью этого метода) указывают на < a href="https://github.com/eventmachine/eventmachine/blob/v1.0.8/lib/eventmachine.rb#L1057" rel="nofollow">метод spawn_threadpool в EventMachine. Этот код в EventMachine вызывается, когда другой код вызывает EventMachine.defer< /a>, метод, который порождает пул из 20 потоков по умолчанию при первом вызове. Я обнаружил использование EventMachine.defer в более старой версии драгоценного камня pubnub (например, здесь), но его также можно использовать из других мест.

Итак, я думаю, что это объясняет большое количество потоков, которые вы наблюдаете на каждом воркере. В основном они ждут в pop методе, который приостанавливает поток до тех пор, пока что-то не будет помещено в очередь (снова отложено в EventMachine). Поэтому, если у вас нет большого количества отложенных операций, потоки в основном ничего не делают.

Если вам не нужно иметь 20 потоков на каждом unicorn worker, готовых к отложенным операциям (скорее всего, вам это не нужно), вы можете попытаться уменьшить количество потоков в пуле, установив параметр threadpoolsize variable до некоторого разумного числа, например:

EventMachine.threadpool_size = 5

Я бы поместил это где-нибудь в блок after_fork в конфигурации единорога.

Кроме того, в качестве другого варианта вы можете использовать гем unicorn-worker-killer для периодического убить рабочих единорога.

Между прочим, сообщения, которые pubnub выплевывает в свой журнал, кажутся нормальными, так как он просто сообщает нам, что он нашел уже инициализированные потоки EventMachine, поэтому ему не нужно запускать новый. Этот исходный код поясняет это.

person BoraMa    schedule 09.04.2016
comment
Круто круто!!!! Я не могу отблагодарить вас за то, что вы поделились таким большим количеством материала. :) :) Если это не слишком невежливо, можете ли вы проверить мою другую проблему - stackoverflow.com/questions/36484097/ спасибо :) - person Steve Robinson; 09.04.2016

Столкнулся с этой проблемой сегодня в версии 4. При использовании PubNub в фоновом режиме количество потоков продолжало расти, пока мы не получили ошибку. Решение было следующим:

client = Pubnub.new(...)
client.publish(...)
client.telemetry.terminate
person MaximusDominus    schedule 25.11.2019