因采用 Flask 原生 WSGI 出现 "Broken pipe" 报错的故障处理
Flask 出现 "Broken pipe" 现象说明:
采用 Flask 原生 WSGI 发布 Web(app.run())。随后,发起一个 Request,在 Request 还未返回前停止查询,并重新发起一个新的 Request。服务端很可能出现类似如下的"Broken pipe"报错。
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usrb64/python2.7/threading.py", line 811, in __bootstrap_inner
self.run()
File "/usrb64/python2.7/threading.py", line 764, in run
self.__target(*self.__args, **self.__kwargs)
File "/usrb/python2.7/site-packages/werkzeugrving.py", line 659, in inner
srv.serve_forever()
File "/usrb/python2.7/site-packages/werkzeugrving.py", line 499, in serve_forever
HTTPServer.serve_forever(self)
File "/usrb64/python2.7/SocketServer.py", line 238, in serve_forever
self._handle_request_noblock()
File "/usrb64/python2.7/SocketServer.py", line 297, in _handle_request_noblock
self.handle_error(request, client_address)
File "/usrb64/python2.7/SocketServer.py", line 295, in _handle_request_noblock
self.process_request(request, client_address)
File "/usrb64/python2.7/SocketServer.py", line 321, in process_request
self.finish_request(request, client_address)
File "/usrb64/python2.7/SocketServer.py", line 334, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "/usrb64/python2.7/SocketServer.py", line 649, in __init__
self.handle()
File "/usrb/python2.7/site-packages/werkzeugrving.py", line 216, in handle
rv = BaseHTTPRequestHandler.handle(self)
File "/usrb64/python2.7/BaseHTTPServer.py", line 340, in handle
self.handle_one_request()
File "/usrb/python2.7/site-packages/werkzeugrving.py", line 251, in handle_one_request
return self.run_wsgi()
File "/usrb/python2.7/site-packages/werkzeugrving.py", line 193, in run_wsgi
execute(self.server.app)
File "/usrb/python2.7/site-packages/werkzeugrving.py", line 184, in execute
write(data)
File "/usrb/python2.7/site-packages/werkzeugrving.py", line 152, in write
self.send_header(key, value)
File "/usrb64/python2.7/BaseHTTPServer.py", line 401, in send_header
self.wfile.write("%s: %s\r\n" % (keyword, value))
IOError: [Errno 32] Broken pipe
"Broken pipe" 报错原因:<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">
"Broken pipe" 的字面意思为 "管道破裂",本质为写入端反馈时读端却关闭,因而造成没有及时取走管道中的数据,从而引发程序异常。
"Broken pipe" 报错处理方式:
放弃对 Flask 原生 WSGI 的使用,转而使用全功能的 WSGI,例如:gunicorn、uWSGI 等。
多种 WSGI 对引发 "Broken pip" 报错操作的响应对比:
1.Flask 原生 WSGI
采用 Flask 原生 WSGI 的最简测试程序如下。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
import time
time.sleep(10)
return 'Hello World'
app.run(host='11.4.76.73', port=6001)
调用方式如下。
# ./env/bin/python flasktest.py
当发起一个 Request,在 Request 还未返回前停止查询,并重新发起一个新的 Request时,WSGI 响应类似如下。
注意:报错"Broken pipe",程序崩溃。
2.gunicorn
采用 gunicorn 的最简测试程序如下。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
import time
time.sleep(10)
return 'Hello World'
调用方式如下。
# ./env/bin/gunicorn -w 1 --log-level 'debug' -b 11.4.76.73:6002 gunicorntest:app
当发起一个 Request,在 Request 还未返回前停止查询,并重新发起一个新的 Request时,WSGI 响应类似如下。
注意:出现"Ignoring connection reset"信息,但不影响应用运行。
3.pywsgi
采用 pywsgi 的最简测试程序如下。
from gevent import monkey
monkey.patch_all()
from flask import Flask
from gevent import pywsgi
app = Flask(__name__)
@app.route('/')
def index():
import time
time.sleep(10)
return 'Hello World'
server = pywsgi.WSGIServer(('11.4.76.73', 6003), app)
server.serve_forever()
调用方式如下。
# ./env/bin/python geventtest.py
当发起一个 Request,在 Request 还未返回前停止查询,并重新发起一个新的 Request时,WSGI 响应类似如下。
注意:应用正常。