框架,即framework,特指为解决一个开放性问题而设计的具备必定约束性的支撑结构,使用框架能够帮你快速开发特定的系统。html
浏览器与服务器之间发起HTTP请求:nginx
1.浏览器发送一个HTTP请求; 2.服务器收到请求,生成一个HTML文档; 3.服务器把HTML文档做为HTTP响应的Body发送给浏览器; 4.浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。
对于全部的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。web
import socket def handle_request(client): buf = client.recv(1024) client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8")) client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8")) def main(): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost',8001)) sock.listen(5) while True: connection, address = sock.accept() handle_request(connection) connection.close() if __name__ == '__main__': main()
接受HTTP请求、解析HTTP请求、发送HTTP响应都是底层的东西,若是要研究这些底层那得花上必定的时间。所以咱们不但愿接触到TCP链接、HTTP原始请求和响应格式,因此,须要一个统一的接口,让咱们专心用Python编写Web业务。
这个接口就是WSGI:Web Server Gateway Interface。flask
Python Web Server Gateway Interface,翻译过来时Python web服务器网关接口,实际上就是一种协议,咱们的应用(Django,Flask)实现了WSGI,就能够配合实现了WSGI(uWSGI,gunicorn)的服务器工做了。
如下是结构图:浏览器
在这种结构里,uWSGI做为服务器,它用到了HTTP协议以及wsgi协议,flask应用做为application,实现了wsgi协议。当有客户端发来请求,uWSGI接受请求,调用flask app获得相应,以后相应给客户端。
这里说一点,一般来讲,Flask等web框架会本身附带一个wsgi服务器(这就是flask应用能够直接启动的缘由),可是这只是在开发阶段用到的,在生产环境是不够用的,因此用到了uwsgi这个性能高的wsgi服务器。服务器
这种结构里,uWSGI做为中间件,它用到了uwsgi协议(与nginx通讯),wsgi协议(调用Flask app)。当有客户端发来请求,nginx先作处理(静态资源是nginx的强项),没法处理的请求(uWSGI),最后的相应也是nginx回复给客户端的。 app
多了一层反向代理有什么好处?负载均衡
提升web server性能(uWSGI处理静态资源不如nginx;nginx会在收到一个完整的http请求后再转发给wWSGI)
nginx能够作负载均衡(前提是有多个服务器)
保护了实际的web服务器(客户端是和nginx交互而不是uWSGI)
框架
from wsgiref.simple_server import make_server def application(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [b'<h1>Hello, web!</h1>'] httpd = make_server('', 8080, application) print('Serving HTTP on port 8080...') # 开始监听HTTP请求: httpd.serve_forever()
浏览器效果:socket
注意:
①整个application()函数自己没有涉及到任何解析HTTP的部分,也就是说,底层代码不须要咱们本身编写,咱们只负责在更高层次上考虑如何响应请求就能够了。
②Python内置了一个WSGI服务器,这个模块叫wsgiref
③application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:
//environ:一个包含全部HTTP请求信息的dict对象;
//start_response:一个发送HTTP响应的函数。
④在application()函数中,调用:
start_response('200 OK', [('Content-Type', 'text/html')])
就发送了HTTP响应的Header,注意Header只能发送一次,也就是只能调用一次start_response()函数。
start_response()函数接收两个参数,一个是HTTP响应码,一个是一组list表示的HTTP Header,每一个Header用一个包含两个str的tuple表示。
一般状况下,都应该把Content-Type头发送给浏览器。其余不少经常使用的HTTP Header也应该发送。
⑤最后,函数的返回值b'<h1>Hello, web!</h1>'将做为HTTP响应的Body发送给浏览器。
调用自己的HTML响应给浏览器
from wsgiref.simple_server import make_server def application(environ, start_response): # start_response('200 OK', [('Content-Type', 'text/html')]) print(environ['PATH_INFO']) path = environ['PATH_INFO'] start_response('200 OK', [('Content-Type', 'text/html')]) f1 = open("index1.html", "rb") data1 = f1.read() f2 = open("index2.html", "rb") data2 = f2.read() if path == "/test1": return [data1] elif path == "/test2": return [data2] else: return ["<h1>404</h1>".encode('utf8')] return [b'<h1>Hello, web!</h1>'] httpd = make_server('', 8080, application) print('Serving HTTP on port 8080...') # 开始监听HTTP请求: httpd.serve_forever()