レール接続の最適化
これはシリーズで3番目のポストです.
これまでに突然と不可解に陰気な応答時間を提供するレールのアプリを経験したことがありますか完全に応答しない?特に環境の中で何も変わっていないときは、特に信じられないほど混乱することができます.
これが起こる最も一般的な理由の1つを見ましょう.
正しくRails接続を構成することは、複雑でありえます.ここでは、それが間違って取得する方法を簡単に説明短いビデオです.
この問題は、プライマリデータベースには分離されないことに注意してください.限られた接続を持つどんなデータストアも構成することは可能です.Postgres、REDIS、memcachedなど.
考慮するこの問題のいくつかの側面があります.
Datastoreはどのように多くのアクティブな接続を合理的にサポートすることが上限を持っています.システム資源は一般にこれらの制限を管理する.例えば、PostgreSQL デフォルトはRedis デフォルトは10000です.デフォルトの接続制限をオーバーライドすることが可能です.ちょうどあなたが何をやっているかを確認してください.
ホスティングプロバイダはさらに制限を課す.毛奥のStandard 0 Postgresは、120の接続で彼らのキャップを計画しますPremium 0 Redis計画キャップ40
接続を確立することは、高価で遅い操作です.Connection pooling あらかじめ確立された接続を再利用することによって接続がどれだけ頻繁に設定されているかを制限することによって、全体の待ち時間を減らします.
接続プーリングから得られる改善された効率は、アプリケーションを単独でdatastore接続限界に基づいて可能であるより、より多くの同時リクエストを提供するのを可能にする.プーリングは力の乗数です.
展開構成は重要な役割を果たします.40の接続の制限を持つデータベースを考えてください.我々は、20の接続を使用するように構成されている2つのサーバーを持つ容量になります.
展開としてのこの問題化合物は、より複雑になります.そして、チャレンジはサーバの数に制限されません.また、サーバごとに実行するプロセス数と各プロセスでアクティブなスレッド数を説明する必要があります.
Railsアプリケーションでは、次の環境変数を使用します. これらは記述的な名前ですが、我々はより良い行うことができると思います.RailsアプリケーションがWebリクエストを提供するよりも多くの場合、数式を見る前にいくつかのより適切な名前を考慮しましょう. また、データベースにアクセスできる外部システムにも影響を与える必要があります.これは別の変数を考慮に入れます. それは現在、数式の上にすべての変数です.
式は非常に簡単です.
2ウェブサーバ、2つのプロセス、8つの糸 3労働者サーバー、4つのプロセス、16の糸 10外部接続
接続の数の式を示します.
上記の展開のための柵の設定の例です.
のようなツールで接続プールをスタックすることが可能ですpg_bouncer , さらに、あなたのRailsアプリケーションがデータベース接続を排出しないようにすることができます.Herokuはこれをサポートしますbuildpack .
プロセスとスレッドの数は、ツールのようなツールの使用を決定するのは難しいことができますSidekiq swarm . ちょうど注意を払って、あなたが数が何であるかについてわかっていることを確認してください.
これまでに突然と不可解に陰気な応答時間を提供するレールのアプリを経験したことがありますか完全に応答しない?特に環境の中で何も変わっていないときは、特に信じられないほど混乱することができます.
これが起こる最も一般的な理由の1つを見ましょう.
データストア接続
正しくRails接続を構成することは、複雑でありえます.ここでは、それが間違って取得する方法を簡単に説明短いビデオです.
この問題は、プライマリデータベースには分離されないことに注意してください.限られた接続を持つどんなデータストアも構成することは可能です.Postgres、REDIS、memcachedなど.
考慮するこの問題のいくつかの側面があります.
接続制限
Datastoreはどのように多くのアクティブな接続を合理的にサポートすることが上限を持っています.システム資源は一般にこれらの制限を管理する.例えば、PostgreSQL デフォルトはRedis デフォルトは10000です.デフォルトの接続制限をオーバーライドすることが可能です.ちょうどあなたが何をやっているかを確認してください.
ホスティングプロバイダはさらに制限を課す.毛奥のStandard 0 Postgresは、120の接続で彼らのキャップを計画しますPremium 0 Redis計画キャップ40
接続プール
接続を確立することは、高価で遅い操作です.Connection pooling あらかじめ確立された接続を再利用することによって接続がどれだけ頻繁に設定されているかを制限することによって、全体の待ち時間を減らします.
接続プーリングから得られる改善された効率は、アプリケーションを単独でdatastore接続限界に基づいて可能であるより、より多くの同時リクエストを提供するのを可能にする.プーリングは力の乗数です.
展開トポロジー
展開構成は重要な役割を果たします.40の接続の制限を持つデータベースを考えてください.我々は、20の接続を使用するように構成されている2つのサーバーを持つ容量になります.
展開としてのこの問題化合物は、より複雑になります.そして、チャレンジはサーバの数に制限されません.また、サーバごとに実行するプロセス数と各プロセスでアクティブなスレッド数を説明する必要があります.
変数
Railsアプリケーションでは、次の環境変数を使用します.
WEB_CONCURRENCY
- プロセス数RAILS_MAX_THREADS
- 糸の数SERVERS
- サーバ/dynosの数PROCESSES
- プロセス数THREADS
- 糸の数EXTERNAL_CONNECTIONS
公式
式は非常に簡単です.
(SERVERS * PROCESSES * THREADS) + EXTERNAL_CONNECTIONS
標準のRails展開を見てみましょう.接続の数の式を示します.
(2 * 2 * 8) + (3 * 4 * 16) + 10 = 234
あなたが利用できるより多くの接続を構成しないことを確実とすることは、重要です.プロビジョニングハードウェアを増やすか、アプリケーションが使用する接続数を減らす必要があるかもしれません.構成
上記の展開のための柵の設定の例です.
# config/database.yml
default: &default
adapter: postgresql
encoding: unicode
pool: <%= ENV["THREADS"] %>
# it's generally a good idea to configure timeouts
connect_timeout: 1
variables:
statement_timeout: 5s
lock_timeout: 2s
# config/initializers/sidekiq.rb
settings = {
url: ENV["REDIS_QUEUE_URL"],
# sidekiq spawns a couple of additional threads,
# so we need to ensure we're using a smaller pool size
size: ENV["THREADS"].to_i - 2, # pool size
# it's generally a good idea to configure timeouts
connect_timeout: 0.2,
read_timeout: 0.5,
write_timeout: 0.5
}
Sidekiq.configure_server do |config|
config.redis = settings
end
Sidekiq.configure_client do |config|
config.redis = settings
end
# config/environments/production.rb
Rails.application.configure do
config.cache_store = :redis_cache_store, {
url: ENV["REDIS_CACHE_URL"],
size: ENV["THREADS"], # pool size
# it's generally a good idea to configure timeouts
connect_timeout: 0.2,
read_timeout: 0.5,
write_timeout: 0.5
}
end
# config/puma.rb
workers ENV["PROCESSES"]
max_threads_count = ENV["THREADS"]
min_threads_count = ENV["THREADS"]
threads min_threads_count, max_threads_count
# Procfile
web: PROCESSES=2 THREADS=8 bin/start-pgbouncer bundle exec puma -C config/puma.rb
worker: PROCESSES=4 THREADS=16 bin/start-pgbouncer bundle exec sidekiq -C config/sidekiq.yml
公式と構成は単純に見えるかもしれません、しかし、それらは一見複雑です.複雑さは展開としてより明白になります.たとえば、異なる接続制限を持つRedisインスタンスによってバックアップされた様々なサイズの展開を考えます.他の展開トポロジーを考えることができますか?数学はどうやってうまくいくのですか.上級オプション
積層プーリング
のようなツールで接続プールをスタックすることが可能ですpg_bouncer , さらに、あなたのRailsアプリケーションがデータベース接続を排出しないようにすることができます.Herokuはこれをサポートしますbuildpack .
Sidekiq群れ
プロセスとスレッドの数は、ツールのようなツールの使用を決定するのは難しいことができますSidekiq swarm . ちょうど注意を払って、あなたが数が何であるかについてわかっていることを確認してください.
Reference
この問題について(レール接続の最適化), 我々は、より多くの情報をここで見つけました https://dev.to/hopsoft/optimizing-rails-connections-4gkdテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol