2016-01-06 9 views
5

私のPython Webアプリケーションには、同じMongoDbサーバーに複数の接続が登録されていますが、異なるデータベースが3つあります。このアプリケーションは、4人のGunicorn社の従業員の下で実行されます。新しいレプリカセットの設定が完了するまでブロックします

私はレプリカセットを使用しています。

プライマリがダウンすると、現在のクエリは失敗し、MongoReplicaSetClient(2.8では同じですが同じです)でリフレッシュがスケジュールされます。次の問合せは、新しいプライマリが時間までに選択され、MonitorThreadがクライアントの接続を更新する情報を取得した場合に成功する可能性があります。

ただし、リフレッシュはこのクライアントにのみ影響します。同じMongoDBサーバーに接続されている他のクライアントは影響を受けません。 これは、各ワーカーが同じMongoDBサーバー上の3つのデータベースに接続されていて、プライマリが失敗したときに3つのデータベースをすべて使用する同じHTTP要求を繰り返すと、接続されたすべてのクライアントを更新するのに不定期な時間がかかることを意味します。各HTTP要求が4人のうちの各ワーカーにラウンドロビンする場合、各Mongoクライアントを更新するための12の要求が必要です。しかし、実際には、リクエストはラウンドロビンにはなりません。

私はプライマリがダウンした場合、self.disconnectself.__schedule_refreshを呼び出すと呼ばれていることがわかりPyMongoコード MongoReplicaSetClient._send_message_with_responseに探しています。このメソッドには、syncという引数があります。これにより、「リフレッシュが完了するまでブロックする」ことができます。

私の考えは、例外をキャッチして、新しいレプリカセットの設定が行われるまで、障害の発生したプライマリとブロックに接続されているすべてのクライアントで__schedule_refresh(sync=True)を呼び出してください。したがって、データベースが正常になるまで、HTTP要求は処理されません(結果は500になります)。

しかし、__schedule_refreshはプライベートメソッドです。また、私はすべてのクライアントでそれを順番に呼び出すのが速いかどうかわかりません - MonitorThreadは間隔で動作します。

おそらくMongoReplicaSetClient.refreshを使用できます。

アイデアについてどう思いますか?それには欠点がありますか?

実装のお手伝いをしますか?

答えて

0

興味深い問題です。

あなたが要求の多くはで来ている環境で実行している場合は、私が出てくるために、主を待っているような、特にネットワーク呼び出しIO、上の任意の作業員ブロックを持つに対してをお勧めします。

私はあなたのmongoクライアントからサーバがダウンしていることを示す可能性のある例外を捕捉しようとし、503秒を呼び出し側に返すことを提案します。 503は一般に、リソースが利用できないことを通知し、後で再試行を提案するための良い方法です。

あなたのmongoデータベース、使用中にダウンして行くと、アプリケーションサーバーがこれを検出した、要求をダンプし、503sを返しますがそれ以外の場合は、ブロック開始スレッドが不足し、アプリケーションサーバーを殺すトラフィックを処理する一つの方法です。これらの呼び出しのすべてをアプリケーションサーバーに送信させて、待機し、失敗する可能性があります。

これは、RESTサービスで使用される一般的なイディオムです:http://www.restpatterns.org/HTTP_Status_Codes/503_-_Service_Unavailable

あなたも「再試行-後」ヘッダクライアントは、将来的に再試行を試みるべきであることを示すために追加することができます。リトライ-Afterヘッダとどのようにいくつかのブラウザがそれを解釈する上でいくつかの詳細情報:

Retry-after HTTP response header - does it affect anything?

HTH

関連する問題