【问题标题】:Large number of threads under unicorn独角兽下的大量线程
【发布时间】:2016-04-08 10:28:58
【问题描述】:

我正在调试我们应用程序中的一些 Posgtres 连接泄漏。几天前,我们突然超过了 100 个连接,而我们不应该这样做 - 因为我们只有 8 个独角兽工人和一个 sidekiq 进程(25 个线程)。

我今天在查看 htop,看到我的独角兽工人产生了大量线程。例如:

我读对了吗?这不应该发生对吗?如果这些是产生的线程,知道如何调试吗?

谢谢!顺便说一句,我的另一个问题 - (Postgres 连接)Debugging unicorn postgres connection leak

编辑

我只是按照这里的一些提示 - 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

这正常吗?线程不应该被杀死吗?这是否也会导致打开不必要的数据库连接? 谢谢

更新: 我刚刚发现我使用的是旧版本的 PubNub gem,它使用 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

【问题讨论】:

  • 我也不认为这是正常的。也许您在应用程序代码中使用了Threads?您能否尝试使用here 中描述的过程从独角兽线程获取堆栈跟踪(尤其请参阅Ruby 在任何特定时刻都在做什么? 部分)?这样,您可能会发现线程徘徊的地方。
  • 哇。感谢该链接@BoraMa
  • 我猜你在database.yml 中配置了reaper_frequency,所以中间线程是Reaper thread,我认为这很正常。我们应该等到线程积累...
  • @BoraMa 啊,好吧。 :) 更新了调查结果。

标签: ruby-on-rails unicorn eventmachine pubnub keen-io


【解决方案1】:

所以,毕竟,在您的特定情况下,这种行为似乎是正常的。

您提供的独角兽线程堆栈跟踪(使用this method 获得)指向the spawn_threadpool method in EventMachine。 EventMachine 中的这段代码在其他代码调用EventMachine.defer 时被调用,该方法在第一次调用时spawns 默认为20 个线程池。我在旧版本的pubnub gem(例如here)中发现了EventMachine.defer 的用法,但它也可以在其他地方使用。

所以,我认为 这解释了您在每个工作人员身上观察到的大量线程。他们大多在pop method 中等待,这会暂停线程,直到有东西被推入队列(在 EventMachine 中再次延迟)。因此,除非您有大量的延迟操作,否则线程大多什么都不做。

如果您不需要在每个 unicorn worker 上为可延迟操作准备 20 个线程(很可能您不需要),您可以尝试通过设置 @ 来减少池中的线程数987654327@ 到某个合理的数字,例如:

EventMachine.threadpool_size = 5

我会把它放在 unicorn 配置的 after_fork 块中的某个地方。

另外,作为另一种选择,您可以考虑使用unicorn-worker-killer gem 定期杀死独角兽的工人。

顺便说一句,pubnub 向其日志中吐出的消息似乎没问题,因为它只是告诉我们它找到了一个已经初始化的 EventMachine 线程,因此它不必启动一个新线程。 This source code 澄清它。

【讨论】:

【解决方案2】:

今天在版本 4 中遇到了这个问题。在后台工作程序中使用 PubNub 时,线程数会继续攀升,直到出现错误。解决方法如下:

client = Pubnub.new(...)
client.publish(...)
client.telemetry.terminate

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    • 2014-01-15
    • 2012-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多