加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

flask 源码浅析(flask 如何处理请求(多线程,多进程,IO多路复用

发布时间:2020-12-20 10:22:25 所属栏目:Python 来源:网络整理
导读:? 2018-04-04 13:09:47 lucky404 阅读数 5724 更多 分类专栏: python ? 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接: https://blog.csdn.net/lucky404/article/details/79815997 之前有阅读过t

?

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/lucky404/article/details/79815997

之前有阅读过tornado 底层的实现,tornado 为了解决C10K 问题(没听说过C10K问题的请查看: http://www.360doc.com/content/13/0522/18/1542811_287328391.shtml),在Linux 平台下是使用了epoll(python2.6 开始支持epoll),unix 平台下 tornado 使用了kque,由于flask 之前没有看过底层的实现,因此趁着清明假期看了一下flask,到底是来一个请求使用一个线程呢,还是进程呢,还是IO多路复用。

涉及到的源码文件

site-packages/flask/app.py,site-packages/werkzeug/serving.py,Lib/socketserver.py

首先肯定要先看入口函数啦

app.py 里面的 run 函数

def run(self,host=None,port=None,debug=None,**options):

该函数通过 run_simple(host,port,self,**options) 启动了socket 服务器(无论是哪个web框架,其实底层都是使用socketserver 监听在某个套接字上来处理请求的)

run_simple 然后到调用 serving.py 里面的make_server

make_server 源码定义如下:

def make_server(host=None,app=None,threaded=False,processes=1,request_handler=None,passthrough_errors=False,ssl_context=None,fd=None): """Create a new server instance that is either threaded,or forks or just processes one request after another. """ if threaded and processes > 1: raise ValueError("cannot have a multithreaded and " "multi process server.") elif threaded: return ThreadedWSGIServer(host,app,request_handler,passthrough_errors,ssl_context,fd=fd) elif processes > 1: return ForkingWSGIServer(host,processes,fd=fd) else: return BaseWSGIServer(host,fd=fd)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

可以看到flask 为我们提供了三种方式来处理请求
1 使用多线程来进行处理
2 使用多进程来进行处理
3 使用poll 或者 select IO多路复用的方式进行处理

BaseWSGIServer 这个类是使用IO 多路复用的
下面有个方法 start_forever

def serve_forever(self): self.shutdown_signal = False try: HTTPServer.serve_forever(self) except KeyboardInterrupt: pass finally: self.server_close()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

我们主要来看HttpServer.serve_forever方法

def serve_forever(self,poll_interval=0.5): """Handle one request at a time until shutdown. Polls for shutdown every poll_interval seconds. Ignores self.timeout. If you need to do periodic tasks,do them in another thread. """ self.__is_shut_down.clear() try: # XXX: Consider using another file descriptor or connecting to the # socket to wake this up instead of polling. Polling reduces our # responsiveness to a shutdown request and wastes cpu at all other # times. with _ServerSelector() as selector: selector.register(self,selectors.EVENT_READ) while not self.__shutdown_request: ready = selector.select(poll_interval) if ready: self._handle_request_noblock() self.service_actions() finally: self.__shutdown_request = False self.__is_shut_down.set()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

_ServerSelector() 定义了 到底该使用select 还是 poll

# poll/select have the advantage of not requiring any extra file descriptor,# contrarily to epoll/kqueue (also,they require a single syscall). if hasattr(selectors,‘PollSelector‘): _ServerSelector = selectors.PollSelector else: _ServerSelector = selectors.SelectSelector
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

对于IO多路复用不熟悉的,推荐查看该文章: https://blog.csdn.net/qq546770908/article/details/53082870

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读