大家好,我有python2.7.5
的下一个环境:
flask==0.10.1
flask-wtf==0.8.4
jinja2==2.7
werkzeug==0.9.1
flask-mongoengine==0.7.0
mongoengine==0.8.2
pymongo==2.5.2
uwsgi==1.9.13
并有下一个应用'app.py':
from flask import Flask
from flask.ext.mongoengine import Document, MongoEngine
from mongoengine import StringField
class Config(object):
DEBUG = True
MONGODB_HOST = ('mongodb://localhost:27017,localhost:27018/'
'test?replicaSet=rs0')
MONGODB_DB = True
app = Flask(__name__)
app.config.from_object(Config)
MongoEngine(app)
class Test(Document):
test = StringField(default='test')
meta = {
'allow_inheritance': False,
}
def __unicode__(self):
return self.test
Test(test='test1').save()
@app.route('/')
def hello_world():
return unicode(Test.objects.first())
if __name__ == '__main__':
app.run('0.0.0.0', 8080, True)
我有下一个nginx配置:
server {
listen 80;
server_name localhost;
location / {
include uwsgi_params;
uwsgi_pass unix:/tmp/uwsgi.sock;
}
}
我开始使用uwsgi:
/path/to/env/bin/uwsgi \
--module app:app \
--env /path/to/env/ \
--pythonpath /path/to/app/ \
--socket /tmp/uwsgi.sock \
--pidfile /tmp/uwsgi.pid \
--daemonize /tmp/uwsgi.log \
--processes 2 \
--threads 2 \
--master
我有两个mongodb实例:
mongod --port 27017 --dbpath /path/to/mongo/data/rs0-0 --replSet rs0 \
--smallfiles --oplogSize 128
和
mongod --port 27018 --dbpath /path/to/mongo/data/rs0-1 --replSet rs0 \
--smallfiles --oplogSize 128
并在mongo控制台中配置副本集:
rsconf = {
_id: "rs0",
members: [{_id: 0, host: "127.0.0.1:27017"}]
};
rs.initiate(rsconf);
rs.add("127.0.0.1:27018");
所以它运作良好。但是,当我向下和向上主要或辅助mongo实例时,我的应用程序无法恢复连接,并且我每次都有下一个例外:
...
File "/path/to/app/replica.py", line 33, in hello_world
return unicode(Test.objects.first())
File "/path/to/env/local/lib/python2.7/site-packages/mongoengine/queryset/queryset.py", line 325, in first
result = queryset[0]
File "/path/to/env/local/lib/python2.7/site-packages/mongoengine/queryset/queryset.py", line 211, in __getitem__
return queryset._document._from_son(queryset._cursor[key],
File "/path/to/env/local/lib/python2.7/site-packages/pymongo/cursor.py", line 470, in __getitem__
for doc in clone:
File "/path/to/env/local/lib/python2.7/site-packages/pymongo/cursor.py", line 814, in next
if len(self.__data) or self._refresh():
File "/path/to/env/local/lib/python2.7/site-packages/pymongo/cursor.py", line 763, in _refresh
self.__uuid_subtype))
File "/path/to/env/local/lib/python2.7/site-packages/pymongo/cursor.py", line 700, in __send_message
**kwargs)
File "/path/to/env/local/lib/python2.7/site-packages/pymongo/mongo_replica_set_client.py", line 1546, in _send_message_with_response
raise AutoReconnect(msg, errors)
pymongo.errors.AutoReconnect: No replica set primary available for query with ReadPreference PRIMARY
当我使用在mongoengie==0.7.10
中使用ReplicaSetConnection
代替MongoReplicaSetClient
的{{1}}时,我有下一个例外:
Down secondary,获取请求,up secondary,获取请求:
我第一次有:
mongoengine==0.8.2
后:
pymongo.errors.AutoReconnect: 127.0.0.1:27017: [Errno 104] Connection reset by peer
向下主要,获取请求,向上主要,获取请求:
我第一次有:
pymongo.errors.AutoReconnect: No replica set primary available for query with ReadPreference PRIMARY
后:
pymongo.errors.AutoReconnect: 127.0.0.1:27017: [Errno 111] Connection refused
向下主要或次要,向上主要或次要,我总是得到请求:
pymongo.errors.AutoReconnect: No replica set primary available for query with ReadPreference PRIMARY
所以两个mongo实例只是简单的例子。如果我再添加一个实例(共3个),那么:
如果我关闭任何二级,那么一切正常。如果我上下一个二级,然后上下或上下二级,那么所有工作也都可以。
如果我上下两个辅助 - 有些问题。
如果我上下初级或只是下一个主要(两个辅助可用) - 一些问题,尽管mongo选择新的主要!!!
如果我启动一个uwsgi进程(没有pymongo.errors.AutoReconnect: not master and slaveOk=false
两个或三个mongo实例):
--master
或使用dev server运行应用程序:
/path/to/env/bin/uwsgi \
--module app:app \
--env /path/to/env/ \
--pythonpath /path/to/app/ \
--socket /tmp/uwsgi.sock \
--pidfile /tmp/uwsgi.pid \
--daemonize /tmp/uwsgi.log \
--processes 1 \
--threads 2
然后应用程序恢复连接在向下和向上mongo实例之后没有问题。
我在生产中有一些部署,有时连接到mongo实例可能会消失(几秒钟)。之后,我的应用程序在重新启动uwsgi之前无法正常工作。
所以我有两个问题:
UPD1 :
我尝试理解问题,现在当我关闭一个mongo节点时获取连接异常时,我对self.__schedule_refresh()
有不同的行为:
对于一个过程:
/path/to/env/bin/python app.py
有两个成员:rs_state
处于有效状态,被up == True
击落。up == False
有一个活跃成员rs_state
。对于两个过程:
up == True
有两个成员:rs_state
处于有效状态,被up == True
击落。up == False
有两个成员:rs_state
处于有效状态,已被up == True
击落(未更改)。当我启动mongo节点时,self.__schedule_refresh(sync=sync)
也有不同的行为:
对于一个过程:
up == False
有一个活跃成员rs_state
。up == True
有两位活跃的rs_state
成员,加上up == True
。对于两个过程:
up == True
有两位活跃的rs_state
成员,加上up == True
。up == False
有两位活跃的rs_state
成员,加上up == True
(未更改)。所以看起来mongo无法更新副本集状态(参见__schedule_refresh
):
up == False
答案 0 :(得分:13)
尝试使用uwsgi --lazy-apps
选项。 MongoReplicaSetClient生成一个replicaset MonitorThread,这个线程不能在uwsgi worker进程fork中生存。 --lazy-apps
将在每个工作进程中初始化pymongo MonitorThread。
答案 1 :(得分:0)
在副本集更改后(没有主要,新的主要等),下一个操作将抛出AutoReconnect异常。在一次失败的操作之后,底层的PyMongo MongoReplicaSetClient将重新连接到副本集,未来的操作可能会成功。
如果有新的主要版本,MongoReplicaSetClient将会找到它并且将来的操作将会成功。
如果没有主要操作,除非将ReadPreference设置为PRIMARY_PREFERRED,否则无法执行任何操作。请参阅此处的文档:
http://mongoengine-odm.readthedocs.org/en/latest/guide/connecting.html#replicasets
每个uwsgi进程必须进行一次重新连接过程。因此,如果您的副本集发生了更改,则每个uwsgi进程可能会出现一个AutoReconnect异常。