我正在调试我们的应用程序中的某些Posgtres连接泄漏。几天前,我们突然间不应该碰到100个连接-因为我们只有8个独角兽工作者和一个sidekiq进程(25个线程)。
我今天在看htop,看到我的独角兽工人产生了许多线程。例如:
我阅读正确吗?这不应该发生吧?如果这些是正在生成的线程,那么如何调试它呢?
谢谢!顺便说一句,我的另一个问题-(Postgres连接)调试独角兽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,它在after_fork中为EventMachine生成了一个线程。
EventMachine的原因是-> https://github.com/keenlabs/keen-gem#asynchronous-publishing
这正常吗?线程不应该被杀死吗?是否还会导致不必要的数据库连接打开?谢谢
更新:我刚刚发现我正在使用使用EM的PubNub gem的旧版本,并且在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
因此,毕竟,在您的特定情况下,该行为似乎是正常的。
您提供(使用此方法获得)的独角兽线程堆栈跟踪指向EventMachine中的spawn_threadpool
方法。调用其他代码时EventMachine.defer
,将调用EventMachine中的此代码,该方法默认在第一次调用时生成20个线程的池。我EventMachine.defer
在较旧版本的pubnub
gem中找到了使用方法(例如here),但也可以在其他地方使用它。
因此,我认为这可以解释您在每个工作线程上观察到的大量线程。他们通常在挂起线程的pop
方法中等待,直到将某些内容推入队列为止(在EventMachine中再次推迟)。因此,除非您有大量的延迟操作,否则线程几乎什么都不做。
如果您不需要在每个独角兽工作者上准备好20个线程来进行可延迟的操作(很可能您不需要),则可以尝试通过将threadpoolsize
变量设置为合理的数量来减少池中的线程数。 :
EventMachine.threadpool_size = 5
我会将其放在after_fork
独角兽配置中的某个位置。
另外,作为另一种选择,您可以考虑使用unicorn-worker-killer宝石定期杀死独角兽的工人。
顺便说一句,pubnub
吐到日志中的消息似乎还可以,因为它只是告诉我们发现了已经初始化的EventMachine线程,因此不必启动新的线程。此源代码对其进行了说明。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句