web-dev-qa-db-ja.com

MongoDBインスタンスのクライアントが有効かどうかをどのように確認しますか?

特に、現在、次の関数を使用して、クライアントへの接続が有効かどうかを確認しようとしています。

def mongodb_connect(client_uri):
    try:
        return pymongo.MongoClient(client_uri)
    except pymongo.errors.ConnectionFailure:
         print "Failed to connect to server {}".format(client_uri)

次に、この関数を次のように使用します。

def bucket_summary(self):
    client_uri = "some_client_uri"
    client = mongodb_connect(client_uri)
    db = client[tenant_id]
    ttb = db.timebucket.count() # If I use an invalid URI it hangs here

無効なURIが指定された場合、最後の行で例外をキャッチしてスローする方法はありますか?私は当初、これがConnectionFailureの目的だと思っていました(したがって、接続時にこれがキャッチされる可能性がありました)が、私は間違っていました。

無効なURIでプログラムを実行すると、実行に失敗し、KeyboardInterruptを発行すると次のようになります。

File "reportjob_status.py", line 58, in <module>
tester.summarize_timebuckets()
File "reportjob_status.py", line 43, in summarize_timebuckets
ttb = db.timebucket.count() #error
File "/Library/Python/2.7/site-packages/pymongo/collection.py", line   1023, in count
return self._count(cmd)
File "/Library/Python/2.7/site-packages/pymongo/collection.py", line 985, in _count
with self._socket_for_reads() as (sock_info, slave_ok):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 17, in __enter__
return self.gen.next()
File "/Library/Python/2.7/site-packages/pymongo/mongo_client.py", line 699, in _socket_for_reads
with self._get_socket(read_preference) as sock_info:
File  "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 17, in __enter__
return self.gen.next()
File "/Library/Python/2.7/site-packages/pymongo/mongo_client.py", line 663, in _get_socket
server = self._get_topology().select_server(selector)
File "/Library/Python/2.7/site-packages/pymongo/topology.py", line 121, in select_server
address))
File "/Library/Python/2.7/site-packages/pymongo/topology.py", line 106, in select_servers
self._condition.wait(common.MIN_HEARTBEAT_INTERVAL)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/threading.py", line 358, in wait
_sleep(delay)
34
Leeren

pymongo.mongo_client.MongoClientserverSelectionTimeoutMSキーワードパラメーターは、ドライバーがサーバーへの接続を試行する時間を制御します。デフォルト値は30秒​​です。

通常の接続時間¹と互換性のある非常に低い値に設定して、すぐにエラーを報告します。接続試行をトリガーするには、その後、DBを照会する必要があります。

>>> maxSevSelDelay = 1 # Assume 1ms maximum server selection delay
>>> client = pymongo.MongoClient("someInvalidURIOrNonExistantHost",
                                 serverSelectionTimeoutMS=maxSevSelDelay)
//                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>>> client.server_info()

これにより、 pymongo.errors.ServerSelectionTimeoutError が発生します。

¹どうやらserverSelectionTimeoutMS0に設定すると、サーバーのレイテンシが非常に低い場合(たとえば、非常に軽い負荷の「ローカル」サーバー)


その例外をキャッチし、適切に処理するのはあなた次第です。以下のようなlike

try:
    client = pymongo.MongoClient("someInvalidURIOrNonExistantHost",
                                     serverSelectionTimeoutMS=maxSevSelDelay)
    client.server_info() # force connection on a request as the
                         # connect=True parameter of MongoClient seems
                         # to be useless here 
except pymongo.errors.ServerSelectionTimeoutError as err:
    # do whatever you need
    print(err)

表示されます:

No servers found yet
44
Sylvain Leroux

こんにちは、接続が確立されているかどうかを確認するには、それを行うことができます:

from pymongo import MongoClient
from pymongo.errors import ConnectionFailure
client = MongoClient()
try:
   # The ismaster command is cheap and does not require auth.
   client.admin.command('ismaster')
except ConnectionFailure:
   print("Server not available")
8

serverSelectionTimeoutMSが機能しません(Python 2.7.12、MongoDB 3.6.1、pymongo 3.6.0)。 A。Jesse Jiryu Davis で提案された GitHubの問題 リトマステストとして最初にソケットレベルの接続を試みること。これは私のためのトリックを行います。

def throw_if_mongodb_is_unavailable(Host, port):
    import socket
    sock = None
    try:
        sock = socket.create_connection(
            (Host, port),
            timeout=1) # one second
    except socket.error as err:
        raise EnvironmentError(
            "Can't connect to MongoDB at {Host}:{port} because: {err}"
            .format(**locals()))
    finally:
        if sock is not None:
            sock.close()

# elsewhere...
Host = 'localhost'
PORT = 27017
throw_if_mongodb_is_unavailable(Host, PORT)
import pymongo
conn = pymongo.MongoClient(Host, PORT)
print(conn.admin.command('ismaster'))
# etc.

これでは捕捉できない多くの問題がありますが、サーバーが実行されていないか到達できない場合は、すぐに表示されます。

1
ESV

serverSelectionTimeoutMS

これは、例外をスローする前にサーバー選択をブロックする時間を定義します。デフォルトは30,000(ミリ秒)です。クライアントレベルで設定可能でなければなりません。データベースオブジェクト、コレクションオブジェクトのレベル、または個々のクエリのレベルで構成することはできません。

このデフォルト値は、典型的なサーバーのプライマリ選択が完了するのに十分であるように選択されました。サーバーが選挙の速度を向上させると、この数値は下方修正される可能性があります。

トポロジーが流動的であるときにサーバー選択の長い遅延を許容できるユーザーは、これをより高く設定できます。トポロジが流動的であるときに「高速でフェール」したいユーザーは、これを小さな数に設定できます。

ゼロのserverSelectionTimeoutMSは、一部のドライバーで特別な意味を持つ場合があります。ゼロの意味はこの仕様では定義されていませんが、すべてのドライバーはゼロの意味を文書化する必要があります。

https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#serverselectiontimeoutms

# pymongo 3.5.1
from pymongo import MongoClient
from pymongo.errors import ServerSelectionTimeoutError

client = MongoClient("mongodb://localhost:27000/", serverSelectionTimeoutMS=10, connectTimeoutMS=20000)

try:
    info = client.server_info() # Forces a call.
except ServerSelectionTimeoutError:
    print("server is down.")

# If connection create a new one with serverSelectionTimeoutMS=30000
0
The Demz