AI智能
改变未来

Django(35)Django请求生命周期分析(超详细)


Django请求生命周期分析

 

1.客户端发送请求

  1. 在浏览器输入url地址,例如
    www.baidu.com

    ,浏览器会自动补全协议(http),变为

    http://www.baidu.com

    ,现在部分网站都实现了

    HSTS

    机制,服务器自动从

    http

    协议重定向到

    https

    协议

  2. 在网页中点击超链接或
    javascript

    脚本进行url跳转,仅设置

    href

    =\’绝对路径\’,浏览器会自动使用当前url的协议、host和port,例如在

    https://tieba.baidu.com/index.html

    网页中,点击一个超链接

    /f?kw=chinajoy

    ,会自动访问

    https://tieba.baidu.com/f?kw=chinajoy

     

2. 路由转发

  1. IP查找:因特网内每个公有IP都是唯一的,域名相当于IP的别名,因为我们无法去记住一大堆无意义的IP地址,但如果用一堆有意义的字母组成,大家就能快速访问对应网站
  2. DNS解析:通过域名去查找IP,先从本地缓存查找,其中本地的
    hosts

    文件也绑定了对应IP,若在本机中无法查到,那么就会去请求本地区域的域名服务器(通常是对应的网络运营商如电信),这个通过网络设置中的

    LDNS

    去查找,如果还是没有找到的话,那么就去根域名服务器查找,这里有所有因特网上可访问的域名和IP对应信息(根域名服务器全球共13台)

  3. 路由转发:通过网卡、路由器、交换机等设备,实现两个IP地址之间的通信。用到的主要就是路由转发技术,根据路由表去转发报文,还有子网掩码、IP广播等等知识点 

3.建立连接

通过TCP协议的三次握手建立连接 

4.传输报文

建立连接后,客户端会通过

TCP

依次、有序的发送一定大小的报文,其中包括了超时重传、阻塞窗口等等概念,用来保证数据包的完整、有序

  • http协议使用的明文传输,所有内容都是直接可读的
  • https协议是基于
    SSL/TLS

    加密,而

    SSL/TLS

    是基于

    TCP

    协议的,也就是

    http

    协议报文包装成

    TCP

    报文进行的加密,使用

    https

    协议的话,如果本地没有证书和公钥,那么会从服务器获取证书并且进行验证,流程如下: 

5.nginx处理

当前

django

框架开发的web项目,主流使用的服务器架构是:

nginx+uWSGI+django
nginx

监听公网IP的某个端口,例如80,接收到请求后,分2种情况处理请求:

  1. 如果是静态资源(如javascript、css、图片等)的请求,那么
    nginx

    直接获取到该资源,返回给用户

  2. 如果是动态内容的请求,那么
    nginx

    就将请求转发到

    uWSGI

    ,使用的协议一般都是

    uwsgi

    ,性能最好

注意:

  • 有些
    reqeust

    会分多个数据包进行发送,

    nginx

    会缓存等待整个

    request

    接收完成才调用

    uWSGI
  • 如果使用的
    https

    ,那么加密、解密都在

    nginx

    中进行处理

 

6.uWSGI处理

uWSGI

监听本机IP的某个端口,例如3308,接收到

nginx

转发来的请求后,通过将

http

协议转换为

WSGI

协议,和

django

程序之间进行通信 

7.WSGIHandler处理

当django接受到一个请求时,会初始化一个

WSGIHandler

,可以在项目下的

wsgi.py

文件进行跟踪查看:

class WSGIHandler(base.BaseHandler):request_class = WSGIRequestdef __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)self.load_middleware()def __call__(self, environ, start_response):set_script_prefix(get_script_name(environ))signals.request_started.send(sender=self.__class__, environ=environ)request = self.request_class(environ)response = self.get_response(request)......

它接受2个参数:

  • environ:是含有服务器端的环境变量
  • start_response:可调用对象,返回一个可迭代对象。

这个

handler

控制了从请求到响应的整个过程,首先的就是加载

django

settings

配置,然后就是调用django的中间件开始操作 

8.middleware中间件处理

django操作中间件,首先会调用

process_request

方法,该方法的作用是处理请求对象,它的参数是

request

,返回有2种情况

  • response:调用process_response列表处理
  • None:调用下一个中间件的process_request处理

返回

response

之后的中间件及其业务逻辑都不会处理,直接回返回给浏览器返回

None

则表示会继续调用下一个中间件,处理下一个中间件中的逻辑 django项目默认有一些自带的中间件,如下:

MIDDLEWARE = [\'django.middleware.security.SecurityMiddleware\',\'django.contrib.sessions.middleware.SessionMiddleware\',\'django.middleware.common.CommonMiddleware\',\'django.middleware.csrf.CsrfViewMiddleware\',\'django.contrib.auth.middleware.AuthenticationMiddleware\',\'django.contrib.messages.middleware.MessageMiddleware\',\'django.middleware.clickjacking.XFrameOptionsMiddleware\',]

process_request

会从上往下依次调用

MIDDLEWARE

中的中间件,注意:中间件的执行是有顺序的,所以我们一般自定义中间件的时候,我们都会将自定义的中间件放到列表最下面 

9.URLConf路由匹配

通过

urls.py

文件中的

urlpatterns

配置找到对应的 视图函数或者视图类的方法,如果没有找到匹配的方法,那么就会触发异常,由中间件的

process_exception

进行处理process_exception:在视图函数或中间件处理过程抛出异常时调用参数:

  • request:请求对象
  • exception:是处理过程中抛出的异常对象

返回:

  • response:之后的
    process_exception

    都不会触发,而是调用

    process_response

    处理

  • None:调用上一个中间件的
    process_exception

    处理

 

10.middleware的process_view

我们通过路由调用视图之前,会调用中间件的

process_view

方法进行预处理process_view:视图预处理,在视图函数处理之前调用参数:

  • view_func:url路由匹配到的视图函数
  • view_args:视图函数的可变参数
  • view_kwargs:视图函数的可变关键字参数

返回:

  • response:调用
    process_response

    处理

  • None:调用下一个中间件的
    process_view

    处理

 

11.views处理request

调用对应的视图函数或视图类的方法处理

request

,例如获取

GET

POST

参数,并且调用特定的模型对象执行数据库操作,如果没有数据库操作,那么就直接跳到我们后续的14步了 

12.models处理

视图方法中,一般情况下都需要调用模型类进行数据操作,一般是通过模型的

manager

管理类进行操作的,如:

MyModel.objects.get(pk=1)

如果没有数据操作,那么这一步和下一步就忽略 

13.数据库操作

如果

django

通过模型类执行对数据库的增删改查,那么此时整个流程就会在对应的数据库中执行 

14.views处理数据

​视图方法获取到数据后:

  • 将数据封装到一个
    context

    字典当中,然后调用指定的

    template.html

    ,通过模板中的变量、标签和过滤器等,再结合传入的数据

    context

    ,会触发中间件的

    process_template_response

    方法,最终渲染成

    HttpResponse
  • 不调用模板,直接返回数据,譬如
    JsonResponse

    FileResponse

  • 执行
    redirect

    ,生成一个重定向的

    HttpResponse

    ,触发中间件的

    process_response

    后,返回到客户端,结束该web请求的生命周期 

15.middleware的process_response

调用中间件的

process_response

方法进行处理,最后一个中间件的

process_response

执行完成后,返回到

WSGIHandler

类中 

16.WSGIHandler处理

WSGIHandler类获取到response后

  • 先处理
    response

    的响应行和响应头,然后调用

    start_response

    返回http协议的 响应行和响应头 到uWSGI,这个

    start_response

    只能调用一次

  • 第一步处理完成后,如果是文件需要对
    response

    进行,否则就直接将

    response

    作为http协议的body部分返回给

    uWSGI

     

17.uWSGI处理

uWSGI接收到django程序的返回后,将所有内容包装成http协议的内容后,通过

uwsgi

协议返回给

nginx

服务器处理 

18.nginx处理

nginx获取到uWSGI的返回后,将response通过TCP协议返回给客户端 

19.客户端接收响应

客户端接收到服务器的响应后,做对应的操作,例如:显示在浏览器中,或是

javascript

的处理等至此,整个web请求的生命周期结束。

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » Django(35)Django请求生命周期分析(超详细)