MongoEngine ReplicaSet 连接在降压时失败
MongoEngine ReplicaSet Connection fails on stepdown
最近我一直在尝试将 Mongoengine 和 Flask 与副本集一起使用。我可以连接,但是当主节点发生变化时,连接会丢失并且出现中断。
这是一个您可以测试行为的片段。它使用非常有用的 http://flip-flop.mlab.com/ 站点来调试副本集问题
from flask import Flask
from mongoengine import connect
from flask_mongoengine import MongoEngine
import os
db = MongoEngine()
app = Flask(__name__)
class TestDoc(db.Document):
texto = db.StringField()
class ProductionConfig:
def get_conn_data(self):
conn = {
'host':"mongodb://testdbuser:testdbpass@flip.mongolab.com:53117,flop.mongolab.com:54117/testdb?replicaSet=rs-flip-flop",
'replicaSet': 'rs-flip-flop'
}
return conn
import time
app.config['MONGODB_SETTINGS'] = ProductionConfig().get_conn_data()
db.init_app(app)
if __name__ == '__main__':
with app.test_client() as c:
while True:
time.sleep(1)
print(TestDoc.objects().count())
TestDoc(texto="1").save()
每次主更改时我都会收到错误:pymongo.errors.AutoReconnect: connection closed
。
非常感谢!我尝试了几个不同的 pyMongo 版本但没有成功。非常非常感谢任何帮助!
这里的问题是新主节点的选举不是即时的。来自 the docs:
It varies, but a replica set will generally select a new primary within a
minute.
For instance, it may take 10-30 seconds for the members of a replica
set to declare a primary inaccessible (see electionTimeoutMillis). One
of the remaining secondaries holds an election to elect itself as a
new primary. During the election, the cluster is unavailable for
writes.
The election itself may take another 10-30 seconds.
在主服务器关闭和副本被选为新主服务器之间的时间里,没有连接可以接受写入(因为它们必须转到主服务器)。
但是,您可以对代码执行一些操作以使其在这些情况下更具弹性。
首先,您应该在连接上设置读取首选项 (more info here):
conn = {
'host':"mongodb://testdbuser:testdbpass@flip.mongolab.com:53117,flop.mongolab.com:54117/testdb",
'replicaSet': 'rs-flip-flop',
'read_preference': ReadPreference.SECONDARY_PREFERRED
}
这意味着在选举期间读取应该非常稳健。
不幸的是,如果没有将所有写入包装在 try
块中,如果它在选举期间尝试写入,您的代码将会失败。
这应该不像您的问题示例中那样是个问题,因为(假设您在烧瓶路径中进行写入)网络服务器将抛出 500 错误响应。当您再次从 flask 请求路由时,选举应该已经完成,mongoengine 将写入新的主节点。
最近我一直在尝试将 Mongoengine 和 Flask 与副本集一起使用。我可以连接,但是当主节点发生变化时,连接会丢失并且出现中断。
这是一个您可以测试行为的片段。它使用非常有用的 http://flip-flop.mlab.com/ 站点来调试副本集问题
from flask import Flask
from mongoengine import connect
from flask_mongoengine import MongoEngine
import os
db = MongoEngine()
app = Flask(__name__)
class TestDoc(db.Document):
texto = db.StringField()
class ProductionConfig:
def get_conn_data(self):
conn = {
'host':"mongodb://testdbuser:testdbpass@flip.mongolab.com:53117,flop.mongolab.com:54117/testdb?replicaSet=rs-flip-flop",
'replicaSet': 'rs-flip-flop'
}
return conn
import time
app.config['MONGODB_SETTINGS'] = ProductionConfig().get_conn_data()
db.init_app(app)
if __name__ == '__main__':
with app.test_client() as c:
while True:
time.sleep(1)
print(TestDoc.objects().count())
TestDoc(texto="1").save()
每次主更改时我都会收到错误:pymongo.errors.AutoReconnect: connection closed
。
非常感谢!我尝试了几个不同的 pyMongo 版本但没有成功。非常非常感谢任何帮助!
这里的问题是新主节点的选举不是即时的。来自 the docs:
It varies, but a replica set will generally select a new primary within a minute.
For instance, it may take 10-30 seconds for the members of a replica set to declare a primary inaccessible (see electionTimeoutMillis). One of the remaining secondaries holds an election to elect itself as a new primary. During the election, the cluster is unavailable for writes.
The election itself may take another 10-30 seconds.
在主服务器关闭和副本被选为新主服务器之间的时间里,没有连接可以接受写入(因为它们必须转到主服务器)。
但是,您可以对代码执行一些操作以使其在这些情况下更具弹性。
首先,您应该在连接上设置读取首选项 (more info here):
conn = {
'host':"mongodb://testdbuser:testdbpass@flip.mongolab.com:53117,flop.mongolab.com:54117/testdb",
'replicaSet': 'rs-flip-flop',
'read_preference': ReadPreference.SECONDARY_PREFERRED
}
这意味着在选举期间读取应该非常稳健。
不幸的是,如果没有将所有写入包装在 try
块中,如果它在选举期间尝试写入,您的代码将会失败。
这应该不像您的问题示例中那样是个问题,因为(假设您在烧瓶路径中进行写入)网络服务器将抛出 500 错误响应。当您再次从 flask 请求路由时,选举应该已经完成,mongoengine 将写入新的主节点。