Flask学习-Wsgiref库

一、前言

前面在Flask学习-Flask基础之WSGI中提到了WerkZeug,我们知道,WerkZeug是一个支持WSGI协议的Server,其实还有很多其他支持WSGI协议的Server。http://wsgi.readthedocs.io/en/latest/servers.html,这里可以看到有uwsgi、werkzeug.servingwsgirefpython-fastcgi等等几十个。wsgiref是官方给出的一个实现了WSGI标准用于演示用的简单Python内置库,它实现了一个简单的WSGI Server和WSGI Application(在simple_server模块中),主要分为五个模块:simple_server, util, headers, handlers, validate。 wsgiref源码地址:https://pypi.python.org/pypi/wsgiref。通过学习Wsgiref,我相信能够更加清晰的了解Web框架的实现。 

二、测试

wsgiref 是 PEP 333 定义的 wsgi 规范的范例实现,里面的功能包括了:

  • 操作 wsgi 的环境变量
  • 应答头部的处理
  • 实现简单的 HTTP server
  • 简单的对程序端和服务器端校验函数

由于simple_server中已经实现了一个简单的WSGI Server和WSGI Application,我们只要直接运行就可以了。

simple_server.py:

if __name__ == '__main__':
httpd = make_server('', 8000, demo_app)
sa = httpd.socket.getsockname()
print "Serving HTTP on", sa[0], "port", sa[1], "..."
import webbrowser
webbrowser.open('http://localhost:8000/xyz?abc')
httpd.handle_request() # serve one request, then exit
httpd.server_close()

  

然后将app运行起来后,结果如下:

三、过程分析

1、Server端启动流程

make_server('localhost', 8000, application)

先查看make_server在wsgiref中的定义:

def make_server(host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler):
    """Create a new WSGI server listening on `host` and `port` for `app`"""
   #  -> HTTPServer.__init__
    #    -> TCPServer.__init__
    # -> TCPServer.server_bind # -> TCPServer.socket.bind # -> TCPServer.server_activate # -> TCPServer.socket.listen
  server = server_class((host, port), handler_class) 
  server.set_app(app)
  return server

  

虽然代码只有三行,但是可以看出生成一个 server 都需要些什么:

    • (host, port):主机名和端口号
    • handler_class:用于处理请求的handler类
    • app 服务器程序在处理时,一定会调用我们之前写好的应用程序,这样他们才能配合起来为客户端面服务,所以,你看到了那个 set_app 调用。

另外,在注释部分,你可以看到那代码背后都发生了什么。

生成 server 实例时,默认的 server_class 是 WSGIServer,它是HTTPServer的子类,后者又是TCPServer的子类,TCPServer又是BaseServer的子类。所以初始化 server 时,会沿着类的继承关系执行下去,最终,生成 server 实例的过程,其实是最底层的 TCPServer 在初始化时,完成了对socket的bind和listen。

后面的 set_app 设置了 app,它会在 handler_class (默认为WSGIRequestHandler)的handle函数中被取出来,然后交给 handler 的 run 函数运行。过程如下:

上图可以看出函数之间的调用关系,也可以看出 make_server 到 使用 socket 监听用户请求的过程。至此,Server端已经起来了。

2、Client端请求过程

httpd.handle_request() 

整个过程可以看出,HTTP建立于TCP之上。

BaseServer最需要注意的是在构造的时候设置了请求处理类RequestHandlerClass

class BaseServer:
      def __init__(self, server_address, RequestHandlerClass):
        """Constructor.  May be extended, do not override."""
        self.server_address = server_address
        self.RequestHandlerClass = RequestHandlerClass
        self.__is_shut_down = threading.Event()
        self.__shutdown_request = False

  

流程走到TCPServer.handle_request,过程如下:

  • 首先一个连接进来,BaseServer监听到连接,调用self._handle_request_noblock()处理
  • self._handle_request_noblock()最终找到finish_request方法
  • finish_request方法实例化请求处理类RequestHandlerClass
RequestHandlerClass是由调用make_server()时传入的handler_class
def make_server(
    host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler
):
    """Create a new WSGI server listening on `host` and `port` for `app`"""
    server = server_class((host, port), handler_class)  #WSGIServer(server_address, RequestHandlerClass)
  server.set_app(app) return server

  

猜你喜欢

转载自www.cnblogs.com/skyflask/p/9220768.html