Büyük/küçük resim: Bu düzenlemeyi düşündüğümüzden beri aşağıdan aşağıya doğru sürükledim. Bence bu şimdi bir marjinal sorunun daha kesin bir açıklaması. OP ile ilgili yorumlar bu nedenle tamamen korelasyon gösteremez. raylar/puma projelerinde yayınlanmıştır`ActiveRecord with_connection do` & ActionController :: Live
Düzenleme hafifçe değiştirilmiş versiyonu: https://github.com/rails/rails/issues/21209, https://github.com/puma/puma/issues/758
Düzenleme Şimdi OS X ve Rainbows
Özeti ile çoğaltılabilir:Puma kullanarak ve koşu uzun bağlantıları çalıştırarak sürekli olarak ActiveRecord bağlantıları geçiş konularıyla ilgili hatalar alıyorum. Bu, kendisinimessage type 0x## arrived from server while idle
ve kilitli (çökmüş) bir sunucuda gösterir.
kurmak:
- Ubuntu 15/OSX Yosemite
- PostgreSQL (9.4)/MySQL (
mysqld 5.6.25-0ubuntu0.15.04.1
) - Yakut - MRG
2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
/Rubiniusrbx-2.5.8
- Raylar (
4.2.3
,4.2.1
) - Puma (
2.12.2
,2.11
) - pg (
pg-0.18.2
)/mysql2
Not Yukarıdaki sürümleri tüm kombinasyonları denenmiştir. İlk listelenen sürüm şu anda test ettiğim şey.
rails new issue-test
- ekle bir denetleyici bir rota
get 'events' => 'streaming#events'
- ekle
streaming_controller.rb
- ayarlama veritabanı şeyler (
pool: 2
, ancak farklı havuz boyutları ile görülen)
Kodu:
class StreamingController < ApplicationController
include ActionController::Live
def events
begin
response.headers["Content-Type"] = "text/event-stream"
sse = SSE.new(response.stream)
sse.write({:data => 'starting'} , {:event => :version_heartbeat})
ActiveRecord::Base.connection_pool.release_connection
while true do
ActiveRecord::Base.connection_pool.with_connection do |conn|
ActiveRecord::Base.connection.query_cache.clear
logger.info 'START'
conn.execute 'SELECT pg_sleep(3)'
logger.info 'FINISH'
sse.write({:data => 'continuing'}, {:event => :version_heartbeat})
sleep 0.5
end
end
rescue IOError
rescue ClientDisconnected
ensure
logger.info 'Ensuring event stream is closed'
sse.close
end
render nothing: true
end
end
Puma yapılandırma:
workers 1
threads 2, 2
#...
bind "tcp://0.0.0.0:9292"
#...
activate_control_app
on_worker_boot do
require "active_record"
ActiveRecord::Base.connection.disconnect! rescue ActiveRecord::ConnectionNotEstablished
ActiveRecord::Base.establish_connection(YAML.load_file("#{app_dir}/config/database.yml")[rails_env])
end
- Run sunucusu
puma -e production -C path/to/puma/config/production.rb
Testi komut:
#!/bin/bash
timeout 30 curl -vS http://0.0.0.0/events &
timeout 5 curl -vS http://0.0.0.0/events &
timeout 30 curl -vS http://0.0.0.0/events
Bu makul tutarlı PostgreSQL (uygulama sunucusu tam bir kilit ile sonuçlanır Notları görmek).Epeyce ekstra unsurlar var 'gerçek-dünya' olarak
message type 0x44 arrived from server while idle
message type 0x43 arrived from server while idle
message type 0x5a arrived from server while idle
message type 0x54 arrived from server while idle
ve sorunun rastgele kendini göstermektedir: korkutucu mesaj libpq
geliyor. Araştırmam bu mesajın libpq
'dan geldiğini ve 'iletişim sorununun alt metni olduğunu, muhtemelen' farklı konularda bağlantı kullanarak gösteriyor. Sonunda, bu yazılırken, herhangi bir günlüğünde tek bir mesaj olmadan sunucuyu kilitledim.
Yani, soru (lar):
- Bir şekilde yasal olmayan takip ediyorum desen var mı? Benim neyim var [sed | understood]?
- Burada veritabanı bağlantılarıyla çalışmak için 'standart' bu sorunlardan kaçınılması gereken nedir?
- Bunu güvenilir bir şekilde yeniden üretmenin bir yolunu görebiliyor musunuz?
veya
- Burada altta yatan bir konudur ve bunu nasıl çözebilir?
MySQL
MySQL çalışan, ileti biraz farklıdır ve (yine de biraz tanımlanmamış durumda sonra ise emin değilim gerçi) uygulaması kurtarır:
F, [2015-07-30T14:12:07.078215 #15606] FATAL -- :
ActiveRecord::StatementInvalid (Mysql2::Error: This connection is in use by: #<Thread:[email protected]/home/dev/.rbenv/versions/2.2.2/lib/ruby/gems/2.2.0/gems/actionpack-4.2.3/lib/action_controller/metal/live.rb:269 sleep>: SELECT `tasks`.* FROM `tasks` ORDER BY `tasks`.`id` ASC LIMIT 1):
with_connection işlevini kullanarak ActiveRecord belgelerinden, bağımsız değişken tamamlandı olarak iletilen bloğa güvenir. Tamamladığından emin misin? Base.connection veya checkout ile bağlantıya ne dersin? – Grasshopper
@Grasshopper - teşekkürler! Bunun, bağlantının (saat) kullanım ömrü boyunca açık bir şekilde bağlantı kurmasını ve böylece bağlantı havuzumu oldukça hızlı bir şekilde yiyeceğinden endişeleniyorum. Sanırım tamamlanmama yolu, eğer bir nedenden ötürü sse.write bloklar varsa ve iş parçacığı sadece orada oturursa, yani eğer bağlantı gitti ve bir sebepten ötürü geri dönmezse? (Bu, libpq'den gelen thread-problem tabanlı mesajları tam olarak açıkladığından emin değilim). (Bu yönde birkaç şeyle deney yapacağız) – button
Açıkladığınız sorun, bağlantıların serbest bırakılmadığı senaryolarda gerçekleşebilir. Aramayı with_connection bloğundan sse.write'e kaldırabilir misiniz? – Grasshopper