我有一个简单的python网络服务器,它在2天/3天后一直失败。经过调查,这是因为它达到了其打开的文件数限制。打开的文件描述符是套接字。 (ls -l /proc/pid/fd/xxx
:/proc/pid/fd/xxx -> socket:[yyyyy]
)
我可以增加ulimit,但是我想弄清楚发生了什么。
一些上下文
我是唯一使用此页面的人,正如我所说的,每小时随机分发到服务器的请求只有50个
问题可能源于:
getjson
打开了一个套接字,并且从不关闭它(可能是,但我不认为是这样,因为我重新启动了服务器并且没有进入监视页面)main的代码:
import listener_handler
from flask import Flask
if __name__ == '__main__':
app = Flask(__name__)
listener_handl = None
@app.route('/listener', methods=['POST'])
def listener():
global listener_handl
if listener_handl is None:
listener_handl = listener_handler.ListenerHandler()
return listener_handl.Post()
... (other handlers for the getjson and the static monitoring page)
app.run()
处理程序的代码:
from flask import request
class ListenerHandler:
def Post(self):
Save(request.form.get('machine_id'), request.form.get('cpu_usage'))
return 'ok'
mongo db的代码:
import pymongo
mongo_client = pymongo.MongoClient()
mongo_db = mongo_client.stations_monitoring
def Save(machine_id, cpu_usage):
mongo_db.db['monitoring'].save({'machine': machine_id, 'cpu': cpu_usage})
我试图使代码保持轻量级,我对python有很好的经验,但是对python webserver几乎没有经验,所以我真的不知道在定义处理程序时,如果每次都创建一个新的套接字,它到底是怎么回事。最后关闭,...
我首先有一个 flask 服务器(代码在这里),然后移到 Tornado (用一些 Tornado 进口和一些
app.run
代替了IOLoop.instance().start()
),但这导致了同样的问题 最佳答案
我在flask和pymongo之间遇到了完全相同的问题;我通过清理每个请求解决了它。如果您出于性能方面的考虑而将MongoClient句柄保持打开状态,则可以将其关闭。
http://api.mongodb.org/python/current/api/pymongo/mongo_client.html#pymongo.mongo_client.MongoClient.disconnect
import pymongo
class MongoConnector:
def __init__(self):
client = pymongo.MongoClient()
self.db = client.stations_monitoring
def close(self):
self.db.disconnect()
def Save(machine_id, cpu_usage):
mongoConnector = MongoConnector()
mongoConnector.db['monitoring'].save({'machine': machine_id, 'cpu': cpu_usage})
mongoConnector.close()
Flask是单线程的,您的WSGI处理程序将生成所需数量的单个应用程序,因此您无需担心Flask级别上的线程支持。
如果您确实要保留mongo连接并出于性能的考虑而这样做,则MongoClient支持带有重新连接的AutoReconnect异常,因此您不必自己处理它。
import pymongo
from pymongo.errors import AutoReconnect
class MongoConnector:
def __init__(self):
client = pymongo.MongoClient()
self.db = client.stations_monitoring
def close(self):
self.db.disconnect()
mongoConnector = MongoConnector()
def Save(machine_id, cpu_usage):
try:
mongoConnector.db['monitoring'].save({'machine': machine_id, 'cpu': cpu_usage})
except AutoReconnect:
#should be reconnected now
mongoConnector.db['monitoring'].save({'machine': machine_id, 'cpu': cpu_usage})
[编辑]不知道你为什么不工作。尝试简化您的工作。如果您没有使用 setter/getter 的理由,那就简单一点。
testflask.py
from flask import Flask, request
import pymongo
app = Flask(__name__)
def SaveLog(machine_id, cpu_usage):
mc = pymongo.MongoClient()
db = mc.stations_monitoring
db['monitoring'].save({'machine': machine_id, 'cpu': cpu_usage})
mc.disconnect()
@app.route('/listener', methods=['POST', 'GET'])
def listener():
SaveLog(request.form.get('machine_id'), request.form.get('cpu_usage'))
return 'ok'
if __name__ == '__main__':
app.run()
test_get.py向服务器发送请求。矿井可以达到〜50/s
import requests
from random import randint
while True:
r = requests.get('http://localhost:5000/listener?machine_id=%s&cpu_usage=%s' %(randint(1,10000), randint(1,100)))
print r.text
验证fds(我的文件卡在5-10个打开的文件句柄周围)
ps aux | grep testflask.py | grep -v grep | awk '{print $2}' | xargs -I @ bash -c 'ls -l /proc/@/fd/ | wc -l'
关于python - python Web服务器上打开的套接字数量不断增加,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20540129/