これは物事を設定する適切な方法ですか?「/」にアクセスするたびにデータベース接続を作成するのとは対照的です。この後者の場合、一度に数百万の接続を持つことができます。それは落胆ですか?このようなアプローチの利点と欠点は何ですか?
1 つの接続を開いてから使用することは望ましくありません。あなたが使用している、Scotty を支える HTTP サーバーは、Warp と呼ばれます。Warp はマルチコア、マルチグリーン スレッド設計です。すべてのスレッドで同じ接続を共有することが許可Database.MongoDB
されています。接続はスレッドセーフであると明確に述べているためですが、1 つのスレッドが応答を待ってブロックされると ( MongoDB プロトコルは単純な要求応答設計に従います) 、すべてのWeb サービスのスレッドがブロックされます。これは残念です。
代わりに、リクエストごとに接続を作成できます。これにより、あるスレッドが別のスレッドをブロックするという問題は簡単に解決されますが、それ自体が問題の共有につながります。TCP 接続をセットアップするオーバーヘッドも、実質的ではありませんが、ゼロではありません。ソケットを開いたり閉じたりするたびに、ユーザーからカーネルにジャンプし、カーネルが内部データ構造を更新するのを待ってから戻る必要があることを思い出してください (コンテキスト スイッチ)。また、TCP ハンドシェイクとさよならも処理する必要があります。また、負荷が高いと、ファイル記述子またはメモリが不足します。
その間のどこかに解決策があればいいのですが。解決策は
- スレッドセーフ
- オペレーティング システムの有限のリソースを使い果たしてしまわないように、接続数を最大に制限しましょう。
- 素早い
- 通常の負荷でスレッド間で接続を共有する
- 負荷の増加に伴い、新しい接続を作成します
- 負荷が軽減された状態で接続が削除されるため、リソースをクリーンアップできます (ハンドルを閉じるなど)。
- 願わくば、他の本番システムによってすでに作成され、実戦でテストされていることを願っています
resource-pool が取り組むのはまさにこの問題です。
プール (Data.Pool) を使用することになっていると言う人もいます。同じデータベース接続を同時に使用する訪問者の数を制限するのに役立つだけのようです. しかし、なぜ私はそれをしたいのでしょうか? MongoDB 接続には、同時使用のサポートが組み込まれていませんか?
同時使用の意味が不明です。私が推測できる解釈が 1 つあります。それは、プロトコルにパイプラインが組み込まれている HTTP/2 のようなものを意味します。
パイプラインの標準的な図 http://research.worksap.com/wp-content/uploads/2015/08/pipeline.png
上記では、クライアントが応答を待たずにサーバーに複数の要求を行っていることがわかります。その後、クライアントはある順序で応答を受け取ることができます。(時間は上から下に流れます。) この MongoDB にはありません。これはかなり複雑なプロトコル設計であり、クライアントに接続プールを使用するように要求するよりも優れているとは言えません。ここでは MongoDB だけではありません。単純な要求と応答の設計は、Postgres、MySQL、SQL Server、および他のほとんどのデータベースが採用したものです。
そして、接続プールは、すべてのスレッドがブロックされ、ユーザーに読み込みバーが表示される前に、Web サービスとして実行できる負荷を制限することは事実です。しかし、この問題は 3 つのシナリオ (接続プーリング、1 つの共有接続、要求ごとに 1 つの接続) のいずれにも存在します。コンピュータのリソースには限りがあり、十分な負荷がかかると、ある時点で何かが崩壊します。接続プーリングの利点は、拡張できないところまで適切に拡張できることです。より多くのトラフィックを処理するための正しい解決策は、コンピューターの数を増やすことです。この問題だけを理由にプーリングを避けるべきではありません。
上記のアプリで、データベース接続が何らかの理由で失われ、再度作成する必要がある場合はどうなりますか? そこからどのように回復しますか?
この種の what-if は Stack Overflow の範囲外であり、「試してみてください」以上の答えはないと思います。サーバーが接続を終了することを考えると、何が起こるかを突き止めることができます: Warp が要求ごとに緑色のスレッドをフォークすると仮定すると (そうすると思います)、各スレッドはIOException
閉じられたスレッドに書き込もうとするときにunchecked を経験します。 TCP 接続。Warp はこの例外をキャッチし、HTTP 500 として提供し、ログにも役立つ情報を書き込みます。現在のような単一接続モデルを想定すると、「再起動」する賢い(ただしコード行が多い)ことを行うことができますmain
機能し、2 番目の接続をセットアップします。私が趣味のプロジェクトで行っていること: 接続が切断されたなどの異常が発生した場合、スーパーバイザー プロセス (systemd など) にログを監視して Web サービスを再起動するように依頼します。金儲けをしている実動 Web サイトにとっては明らかに優れたソリューションではありませんが、小規模なアプリには十分に機能します。
auth
関数による認証はどうですか?auth
関数は、パイプの作成後に 1 回だけ呼び出す必要がありますか?それとも、"/" にヒットするたびに呼び出す必要がありますか?
接続の作成後に一度呼び出す必要があります。MongoDB 認証は接続ごとです。コマンドが現在のクライアント接続に対応する MongoDB サーバーのデータ構造を変更する方法の例をここでdb.auth()
見ることができます。