• django进阶---从WSGI的介绍到django原理解析


         WSGI(Web 服务器网关接口)是python中所定义的Web Server和Web APP之间或框架之间的接口标准规范。当使用 Python 进行 web 开发时,要深刻理解 Django、Flask、Tornado等 web 框架,WSGI是你绕不过去的槛儿。
         WSGI接口规范的目的就是规范Web服务器与Web应用之间的交互,在协议之间进行转换。
         WSGI将Web组件分成三类:
         1. Web服务器(Server): 监听某个端口的http服务器
         2. Web中间件(Middleware): 处于服务器和应用中间,起到承接的作用,用python的术语来说,中间件就类似于一个装饰器
    例如: def app(environ, start_response):   这是一个app
                  return []
     
    那么中间件通常是这样定义:
             def  middleware(environ, start_response):
                    //这里编写中间件的代码
                    return app(environ, start_response)
     
         3. Web应用程序(APP): 指的是可以被调用的一个对象,一般指的是一个函数 或者 包含一个__call__方法的类的实例
     
    django 整个项目实际上也是这三部分组成,我们在执行python manage.py runserver 的时候,
    就首先启动了一个8000端口的http服务器(这个就是Web服务器)
    然后 django里面的中间件(这个就是上述所说的Web中间件),这个是定义在 settings.py 文件的 MIDDLEWARE
    最后 django加载里面的app(这个就是上述所说的Web应用程序),这个是定义在 settings.py 文件的 INSTALLED_APPS

    什么是WSGI APP:

    WSGI APP是一个可调用的对象(callable object),常用的可调用的对象有三种:

    1.一个函数或者类的方法:

    def app(environ, start_response):   这是一个app
          return []
     
    2.一个实现__call__()方法的类的实例:

    class app:

        def __call__(environ, start_response):

             start_response('200 OK', [('Content-Type', 'text/html')])

             return []   

          

    这个可调用的对象有几点需要说明一下:

    1. 接收两个参数environ和start_response:
    environ是一个字典,里面储存了HTTP request的所有内容。在django里面,通常会把environ 封装成为一个request。

    start_response是一个WSGI Server(http 服务器)传递过来的函数,用于将response header,  status传递给Server。

    start_response(status, headers), 它的作用是返回状态码 以及 头部信息, status必须是一个字符串,格式是 “状态码 + 说明”。

    headers 是一个数组,按照 [(key, value), (key, value) ] 这样的格式来组织。

    2.它需要返回一个可迭代的值,用于将response body传递给Server。

    ["hello world", "baby"]

    WSGI Server

    WSGI Server可以理解为就是一个实现了wsgi协议的http服务器,使用wsgi协议的方式来调用WSGI APP。

    通常来说,它由两部分组成:
    1. http 服务器: 这里具体的代码就不写了,大概就是
     
    socket = eventlet.listen(('localhost', '8000'), backlog = 10)  定义一个wsgi http服务器
    server = eventlet.spawn(event.wsgi.server, socket, app) 把service 和 app进行绑定
                                      
    2. 调用app的主方法:
    def run(application): #服务器程序调用应用程序
    
        environ = {}#设定参数
    def start_response(status, headers): #设定状态和头部参数的回调函数 pass result = application(environ, start_response)#调用APP def write(data): # 这是把响应发到前端的函数 pass def data in result: # 迭代访问,把响应发到前端 write(data)
    服务器程序主要做了以下的事:
      1. 设定app所需要的参数(environ,start_response)
      2. 调用app
      3. 迭代访问app的返回结果(response body),并传给客户端

    但实际上已经有很多已经封装好的WSGI Server供我们使用,只需简单的将APP与一些其他的参数绑定来创建一个Server
    而这个Server会将它接收到的request传递给绑定的APP。

    下面是django自带的服务器:

    from wsgiref.simple_server import make_server
    
    # 定义我们一个最简单的app
    def application(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        return [b'<h1>Hello, web!</h1>']
    
    # 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
    httpd = make_server('', 8000, application)
    print('Serving HTTP on port 8000...')  # 开始监听HTTP请求:
    httpd.serve_forever()
    

      


    看, 我们已经自己编写了一个最基础的django,是不是很激动,django的本质就是这样的一种形式,是不是感觉发现了新大陆。

    WSGI Middleware

    middleware的概念没有appllication和server那么容易理解。
    假设一个符合application标准的可调用对象,它接受可调用对象作为参数,返回一个可调用对象的对象。
    那么对于server来说,它是一个符合标准的可调用对象,因此是application。
    而对于application来说,它可以调用application,因此是server。
    这样的可调用对象称为middleware。

    middleware的概念非常接近decorator。

    中间件对于app来说,它是一个service. 但是对于service来说,它确实一个app。文字说的不清晰,还是用代码来说比较好。

     

    # 这是一个标准的application object
    def index(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        return ['index page']
    
    # 这是一个标准的application object
    def hello(environ, start_response):
        start_response('200 OK', [('Content-Type', 'text/html')])
        return ['hello page']
    
    # 这是一个标准的application object
    def not_found(environ, start_response):
        start_response('404 NOT FOUND', [('Content-Type', 'text/plain')])
        return ['Not Found Page']
     
    ###上面我们定义了三个app
    ### 然后我们定义一个中间件 middleware, 看到没有,这个中间件的形式是跟app是一样的
    def application(environ, start_response):
        path = environ.get('PATH_INFO', '').lstrip('/')  #这句代码是获取url
        
         urls = [  # 这里定义路由
             ('index', index),
             ('hello', hello)
         ]
         
         for item in urls:  # 这里根据路由,执行不同的app
              if item[0] == path:
                   app = item[1]
                   return app(environ, start_response)
         else:     return not_found(environ, start_response) # 如果找不到,则执行默认的app
    from wsgiref.simple_server import make_server
    
    # 创建一个服务器,IP地址为空,端口是8000,处理函数是application:
    httpd = make_server('', 8000, application)
    httpd.serve_forever()
    

      

     
    看到没有,这个例子比上面的更加完善,利用中间件实现了路由的功能,把django最基础的功能完整的展示出来
     
    中间件除了路由之外,还可以做很多事情,最常见的还有:
    • 负载均衡,转发用户请求
    • 预处理 XSL 等相关数据
    • 限制请求速率,设置白名单
    等等等
     

  • 相关阅读:
    CentOS 7.4 安装python3及虚拟环境
    【抓包工具之Fiddler】增加IP列;session高亮
    【抓包工具之Fiddler】导出jmeter脚本
    Python2.7 Centos安装
    Centos 轻松升级 GCC 不改变系统环境
    GraphLab 安装 出错 "Cannot uninstall 'boto'" "Cannot uninstall 'certifi'"
    Centos6 使用 gbdt lightgbm "libc.so.6: version `GLIBC_2.14' not found" "Segment Fault"
    Linux 安装 gbdt xgboost lightgbm
    Sudo Permission Denied
    Linux Load Average高但磁盘IO和CPU占用率不高的可能原因
  • 原文地址:https://www.cnblogs.com/wilken/p/12785610.html
Copyright © 2020-2023  润新知