django框架--底层架构
零、参考
https://www.jianshu.com/p/679dee0a4193
https://www.letiantian.me/2015-09-10-understand-python-wsgi/
一、对于web服务的理解
web
服务应该至少包含两个模块:web
服务器和web
应用程序,两个模块在功能和代码上解耦。
web
服务器负责处理socket
调用、http
数据解析和封装等底层操作。
web
应用程序负责业务处理、数据增删改查、页面渲染/生成等高层操作。
web
服务器一旦接收到http
请求,经过自身的解析后就会调用web
应用程序来处理业务逻辑,并得到web
应用程序的返回值,再经过自身的封装发送给客户端。
二、对于wsgi协议的理解
在web
服务器和web
应用程序之间需要定义一个接口规则,这也叫协议,用于明确两者之间以什么样的形式交互数据。即:web
服务器应该以什么样的形式调用web应用程序,而web
应用程序又应该定义成什么形式。
python
下规定的web
服务的接口规则叫做wsgi
,wsgi
协议对于server
和application
的接口定义如下:
对于server
调用规则的定义:
response = application(environ, start_response)
对于application
接口编码的定义:
def application(environ, start_response):
status = '200 OK'
response_headers = [('Content-Type', 'text/plain'),]
start_response(status, response_headers)
return [b'hello',]
只要是遵从如上形式进一步封装server
和application
的,均称为实现了wsgi
协议的server/application
。
python
内置提供了一个wsigref
模块用于提供server
,但是只能用于开发测试,django
框架就是使用此模块作为它的server
部分,也就说,实际生产中的server
部分,还需要使用其他模块来实现。
任何web
框架,可能没有实现server
部分或者只实现一个简单的server
,但是,web
框架肯定实现了application
部分。application
部分完成了对一次请求的全流程处理,其中各环节都可以提供丰富的功能,比如请求和响应对象的封装、model/template
的实现、中间件的实现等,让我们可以更加细粒度的控制请求/响应的流程。
三、自定义一个简单的基于wsgi协议的web框架
django
框架的server
部分由python
内置的wsgiref
模块提供,我们只需要编写application
应用程序部分。
from wsgiref.simple_server import make_server
def app(environ, start_response): # wsgi协议规定的application部分的编码形式,可在此基础上扩展
status = '200 OK'
respones_headers = []
start_response(status, response_headers)
return [b'hello',]
if __name__ == '__main__':
httpd = make_server('127.0.0.1', 8080, app)
httpd.serve_forever()
用以下图示表示简单的web请求流程架构(伪代码)
web
服务器就像是一颗心脏不停的跳动,驱动整个web
系统为用户提供http
访问服务,并调用application
返回响应
四、django中的server实现
django
使用的底层server
模块是基于python
内置的wsgiref
模块中的simple_server
,每次django
的启动都会执行如下run
函数。run
函数中会执行serve_forever
,此步骤将会启动socket_server
的无限循环,此时就可以循环提供请求服务,每次客户端请求到来,服务端就执行django
提供的application
模块。
django
中server
的启动----django.core.servers.basehttp.py
"""
HTTP server that implements the Python WSGI protocol (PEP 333, rev 1.21).
Based on wsgiref.simple_server which is part of the standard library since 2.5.
This is a simple server for use in testing or debugging Django apps. It hasn't
been reviewed for security issues. DON'T USE IT FOR PRODUCTION USE!
"""
def run(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer):
server_address = (addr, port)
if threading:
httpd_cls = type('WSGIServer', (socketserver.ThreadingMixIn, server_cls), {})
else:
httpd_cls = server_cls
httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
if threading:
# ThreadingMixIn.daemon_threads indicates how threads will behave on an
# abrupt shutdown; like quitting the server by the user or restarting
# by the auto-reloader. True means the server will not wait for thread
# termination before it quits. This will make auto-reloader faster
# and will prevent the need to kill the server manually if a thread
# isn't terminating correctly.
httpd.daemon_threads = True
httpd.set_app(wsgi_handler)
httpd.serve_forever()
底层无限循环将作为web
服务的主要驱动----socektserver.py
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()
server
对于application
的调用----wsgiref.handlers.py
def run(self, application):
"""Invoke the application"""
# Note to self: don't move the close()! Asynchronous servers shouldn't
# call close() from finish_response(), so if you close() anywhere but
# the double-error branch here, you'll break asynchronous servers by
# prematurely closing. Async servers must return from 'run()' without
# closing if there might still be output to iterate over.
try:
self.setup_environ()
self.result = application(self.environ, self.start_response)
self.finish_response()
except:
try:
self.handle_error()
except:
# If we get an error handling an error, just give up already!
self.close()
raise # ...and let the actual server figure it out.
五、django中的application实现
django
的application
模块是通过WSGIHandler
的一个实例来提供的,此实例可以被call
,然后根据wsgi
的接口规则传入environ
和start_response
。所以本质上,django
就是使用的内置python
提供的wsgiref.simple_server
再对application
进行丰富的封装。大部分的django
编码工作都在application
部分。
application
的编码定义部分----django.core.handlers.wsgi.py
class WSGIHandler(base.BaseHandler):
request_class = WSGIRequest
def __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)
response._handler_class = self.__class__
status = '%d %s' % (response.status_code, response.reason_phrase)
response_headers = list(response.items())
for c in response.cookies.values():
response_headers.append(('Set-Cookie', c.output(header='')))
start_response(status, response_headers)
if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
response = environ['wsgi.file_wrapper'](response.file_to_stream)
return response
六、django的底层调用链
七、总结
web
服务是基于socket
的高层服务,所以web
服务必须含有web
服务器这一模块。
web
服务需要动态渲染数据,需要中间件来丰富功能,需要封装和解析来处理数据,所以web
服务必须含有web
应用程序这一模块。
web
框架是一种工具集,封装了各种功能的底层代码,提供给我们方便开发的接口。但不论是哪一种框架,它们的底层原理基本都是一致的。
应该深入学习、研究一个web
框架,精通一门框架的实现原理和设计理念。
django框架--底层架构的更多相关文章
- [Python自学] day-18 (2) (MTV架构、Django框架、模板语言)
一.实现一个简单的Web服务器 使用Python标准库提供的独立WSGI服务器来实现MVC架构. 首先,实现一个简单的Web服务器: from wsgiref.simple_server import ...
- Django框架架构总览
Django框架架构总览 理解Django是如何运作的 条目创建于 2013-08-14 1464 views 服务器君一共花费 15.204 ms 进行了 4 次数据库查询,努力地为 ...
- WEB框架-Django框架学习-预备知识
今日份整理,终于开始整个阶段学习的后期了,今日开始学习Django的框架,加油,你是最胖的! 1.web基础知识 1.1 web应用 Web应用程序是一种可以通过Web访问的应用程序,程序的最大好处是 ...
- Django框架理解和使用常见问题
1.什么是中间件? 中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出. 中间件一般做认证或批量请求处理,django中的中间 ...
- 第六模块:WEB框架开发 第1章·Django框架开发1~50
01-Django基础介绍 02-Web应用程序1 03-Web应用程序2 04-http请求协议1 05-http请求协议2 06-http协议之响应协议 07-wsgire模块1 08-wsgir ...
- Django框架的理解和使用的常见问题
1.什么是中间件? 中间件是介于request与response处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出. 中间件一般做认证或批量请求处理,django中的中间 ...
- django(django框架了解,http协议)
Django框架 学习目的: 完成web应用的编写 django的作用: 0.业务逻辑分发(路由分发) 1.业务逻辑实现: 业务逻辑根据分发来完成具体的事,再根据具体事的需求,和页面或数据库交互,返回 ...
- Django框架3——模型
Django数据库层解决的问题 在本例的视图中,使用了pymysql 类库来连接 MySQL 数据库,取回一些记录,将它们提供给模板以显示一个网页: from django.shortcuts imp ...
- MVC其实很简单(Django框架)
Django框架MVC其实很简单 让我们来研究一个简单的例子,通过该实例,你可以分辨出,通过Web框架来实现的功能与之前的方式有何不同. 下面就是通过使用Django来完成以上功能的例子: 首先,我们 ...
随机推荐
- Linux服务器部署系列之一—Apache篇(下)
接上篇 linux服务器部署系列之一—Apache篇(上) 四.管理日志文件 Apache日志分为访问日志和错误日志两种: 1)访问日志 用于记录客户端的访问信息,文件名默认为access_lo ...
- IntelliJ IDEA 2017版 spring-boot 报错Consider defining a bean of type 'xxx' in your configuration问题解决方案
问题分析: 通过问题的英文可知,这个错误是service的bean注入失败,那么为什么会产生这个问题呢? 主要是框架的Application产生的,所以我们建立项目的时候,要保证项目中的类跟Appli ...
- UVa 10269 Adventure of Super Mario (Floyd + DP + BFS)
题意:有A个村庄,B个城市,m条边,从起点到终点,找一条最短路径.但是,有一种工具可以使人不费力的移动L个长度,但始末点必须是城市或村庄.这种工具有k个,每个只能使用一次,并且在城市内部不可使用,但在 ...
- 深度linux没有ll等命令的解决办法
编辑~/.bashrc, 添加alias 如下 vim ~/.bashrc 设置别名. 添加如下行 alias ll='ls -alF' alias la='ls -A' alias vi='vim' ...
- (转载)从Java角度理解Angular之入门篇:npm, yarn, Angular CLI
本系列从Java程序员的角度,带大家理解前端Angular框架. 本文是入门篇.笔者认为亲自动手写代码做实验,是最有效最扎实的学习途径,而搭建开发环境是学习一门新技术最需要先学会的技能,是入门的前提. ...
- volatile 类型修饰符
volatile 类型修饰符 1.解释 就像大家更熟悉的const一样,volatile是一个类型修饰符(type specifier).它是被设计用来修饰被不同线程访问和修改的变量.如果不加入vol ...
- 【spfa训练】HDU4725 (层级建图)
HDU4725 题目大意:一些节点分布在不同的层上,已知相邻的层可以往来距离为c,在给你一些已知的边,问你点1-n的最短路 分析:越往后做,越觉得最短路的考点已经不是spfa算法还是dijkscar算 ...
- Nonsense Alphabet
Nonsense Alphabet A was an ant Who seldom stood still, And who made a nice house In the side of a hi ...
- sqlserver 实现数据变动触发信息
1.建立存储过程,功能是动态写入文件中信息,可以在触发器或存储过程调用. SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO create proc [d ...
- 我要总结基本书 .net稍微有些深度的书籍看看
1. 你必须知道的.NET 2. C# in depth 3.C#并发编程经典实例 4.ASP.NET MVC 4框架揭秘 5.NET最佳实践 6..NET探秘 .NET安全编程 .NET企业服务框架 ...