浅谈瓶源码之请求过程

  

<强>瓶

  

  

瓶是一个使用Python编写的轻量级网络应用框架,让我们可以使用Python语言快速搭建Web服务,瓶也被称为“microframework”,因为它使用简单的核心,用扩展增加其他功能

  

  

我们先来看看python现在比较流行的网框架

  
      <李>瓶李   <李> Django李   <李>龙卷风李   <李> Sanic李   
  

瓶:轻,组件间松耦合,自由,灵活,可扩展性强,第三方库的选择面广的同时也增加了组件间兼容问题

  

Django: Django相当于一个全家桶,几乎包括了所有web开发用到的模块(会话管理,CSRF防伪造请求,形式表单处理,ORM数据库对象化,模板语言),但是相对应的会造成一个紧耦合的情况,对第三方插件不太友好

  

龙卷风:底层通过eventloop来实现异步处理请求,处理效率高,学习难度大,处理稍有不慎很容易阻塞主进程导致不能正常提供服务,新版本也支持asyncio

  

Sanic:一个类瓶框架,但是底层使用uvloop进行异步处理,可以使用同步的方式编写异步代码,而且运行效率十分高效。

  

  

先来看看维基百科对WSGI的定义

  

Web服务器网关接口(Python Web服务器网关接口,缩写为WSGI)是为Python语言定义的Web服务器和网络应用程序或框架之间的一种简单而通用的接口。

  

何为网关,即从客户端发出的每个请求(数据包)第一个到达的地方,然后再根据路由进行转发处理。而对于服务端发送过来的消息,总是先通过网关层,然后再转发至客户端

  

那么可想而知,WSGI其实是作为一个网关接口,来接受服务器传递过来的信息,然后通过这个接口调用后台应用程序里的视图函数进行响应。

  

先看一段有趣的对话:
  

  
  

Nginx:嘿,WSGI,我刚收到了一个请求,我需要你作些准备,然后由瓶来处理这个请求。
  WSGI:好的,Nginx。我会设置好环境变量,然后将这个请求传递给瓶处理。
  瓶:谢谢。WSGI给我一些时间,我将会把请求的响应返回给你。
  WSGI:好吧,那我等你。
  瓶:好的,我完成了,这里是请求的响应结果,请求把结果传递给Nginx。
  WSGI:好!Nginx,这里是响应结果,已经按照要求给你传递回来了。
  Nginx:酷,我收到了,我把响应结果返回给客户端。大家合作愉快~

     

对话里面可以清晰了解到WSGI, nginx,瓶三者的关系

  

下面来看看瓶中的wsgi接口(注意:每个进入瓶的请求都会调用Flask.__call__)
  

        #摘自瓶源码app.py   类瓶(_PackageBoundObject):   #中间省略   def __call__(自我、环境start_response):   回归自我。start_response wsgi_app(环境)      def wsgi_app(自我、环境start_response):   环境:一个包含全部HTTP请求信息的字典,由WSGI服务器解包HTTP请求生成   # start_response: WSGI服务器提供的函数,调用可以发送响应的状态码和HTTP报文头,   #函数在返回前必须调用一次。   :param环境:WSGI环境。   :param start_response:一个可调用的接受状态码,   标题的列表,和一个可选的异常上下文   开始响应。   #创建上下文   ctx=self.request_context(环境)   错误=没有   试一试:   试一试:   #把上下文压栈   ctx.push ()   #分发请求   响应=self.full_dispatch_request ()   除了例外e:   错误=e   响应=self.handle_exception (e)   除了:   错误=sys.exc_info () [1]   提高   #返回结果   start_response返回响应(环境)   最后:   如果self.should_ignore_error(错误):   错误=没有   #上下文出栈   ctx.auto_pop(错误)   之前      

wsgi_app中定义的就是瓶处理一个请求的基本流程,
  1.创建上下文
  2.把上下文入栈
  3.分发请求
  4.上下文出栈
  5 .返回结果

  

其中反应=self.full_dispatch_request()请求分发的过程我们需要关注一下
  

        #摘自瓶源码app.py   类瓶(_PackageBoundObject):   #中间省略   def full_dispatch_request(自我):   self.try_trigger_before_first_request_functions ()   试一试:   request_started.send(自我)   房车=self.preprocess_request ()   如果没有:房车   房车=self.dispatch_request ()   除了例外e:   房车=self.handle_user_exception (e)   返回self.finalize_request (rv)      def dispatch_request(自我):   要求=_request_ctx_stack.top.request   如果要求。routing_exception不是没有:   self.raise_routing_exception(要求)   规则=req.url_rule   如果getattr(规则,provide_automatic_options, False) \   和要求。方法==把∠睢?   返回self.make_default_options_response ()   返回self.view_functions [rule.endpoint] (* * req.view_args)      def finalize_request(自我,房车,from_error_handler=False):   响应=self.make_response (rv)   试一试:   响应=self.process_response(响应)   request_finished。发送(自我,响应=响应)   除了例外:   如果不是from_error_handler:   提高   self.logger。异常(“请求最终失败了,”   当处理一个错误时发生错误)   返回响应      

浅谈瓶源码之请求过程