Django之WSGI淺談

1、什麼是Web框架

框架,即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()
View Code

接受HTTP請求、解析HTTP請求、發送HTTP響應都是底層的東西,若是要研究這些底層那得花上必定的時間。所以咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口,讓咱們專心用Python編寫Web業務。
這個接口就是WSGI:Web Server Gateway Interface。flask

2、WSGI

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)

框架

示例1:

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()
test1.py

瀏覽器效果: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發送給瀏覽器。

示例2:

調用自己的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()
test2.py
相關文章
相關標籤/搜索