Python Flask 概念與實作(二) - Web server概念
前言
我們在本地開發好flask後,到底如何將已經開發好的flask部署到網路當中?網路中查了很多資料,WSGI server、Nginx、Proxy server、Reverse Proxy等等其實各個環環相扣,使用這些工具提高我們server的效率與安全性。
目前 Python Flask 概念與實作 大致規劃為
在開發過程中,Test(測試)其實也很重要,但礙於缺乏經驗,若之後有望的話再補上(專案打包、網站優化等等亦同)
部署Server
在上節Flask model運用時,我們搭建一個本地端的Server,但要真正部署一個「足夠安全」server仍遠遠不夠。
首先,大部分的網站都會有資料庫(database, DB),而實際的狀況與我們開發時使用的SQLite不同的是:DB並不會與網站存在相同的Server主機當中。而是儲存在一個單獨的DB server並且只允許你的Flask(App server)來做存取的行為,倘若User想要存取DB server中的資料時,必須透過App server才能獲得資料。(App server可以控管User的存取行為)
User and Server & DB server
App Server
然而,這種部署方式雖然可行,但仍存在一些問題:
- 隨著網站規模變大,若有大量的請求(request)同時發送到App server時(無論是否為惡意攻擊),Flask效能並不好,也不夠穩定(畢竟Flask也只是單進程)。
- User向Server發送的是HTTP request,在Python中是使用WSGI(Python Web Server GateWay Interface)協定操作HTTP request與response,雖然Flask內建WSGI server但效能僅僅只足夠開發使用。
因此,我們需要一個專門的WSGI server部署Flask(App process),而常見的Gunicorm(操作較簡單)或uWSGI(效能較佳)都是不錯的選擇,這裡我們選擇Gunicorm作為示範。
User and App Server & DB server
Gunicorm是一個支援多進程與多線程的WSGI server,透過Gunicorm部署Flask,可以提升Server的效能。Flask可以更有效率的處理request(相較於Flask內建開發用的server)。
Web Server
目前server的規劃已經滿足大致需求,並且是一個動態伺服器(Dynamic Server),其功能是非常多元的,但仍有幾點是可以改善的:
- 一部分的user單純只是存取靜態資源(e.g. 訪問網站),App server雖然可以處理但仍造成其負擔。
- server的真實位置暴露在外容易被攻擊,其實user根本不在意後端到底是誰🤷🏻,只要滿足其需求即可。
- 隨著網站擴大,主機的效能有可能無法負擔,增加App server的同時,也需要一個server統一對外。
因此我們需要一台Web server來處理上述的缺點,常見的有Apache與Nginx(音同Engine X),聽聞Nginx速度處理靜態資源較快且不處理動態資源,剛好Gunicorm已經勝任這份工作🤓,因此這裡以Nginx作為示範。
User, Web server, App server and DB server
Nginx被設置在最外層,當User發送request時,Nginx(Web server)會先查看request,如果User的request是Web server端已經有的靜態資源,Nginx會直接返回respone,無需在向後傳遞,減少App server的負擔。反之,再傳送到Gunicorm(App server)。
這樣設置的優點是:
- 隱藏App server的真實IP,避免受到攻擊。(反向代理)
- 減少App server的負擔,加速User存取時間。
- 隨著App server數量增加時,每一個App server性能或功能有可能不同,Nginx可以設定有效率的模式分配request給App server。
Reverse Proxy & Forward Proxy
我們都知道網路當中存在許多node(節點),每一個node都是一台主機。在網路的茫茫大海世界如何找到欲訪問的主機IP呢?這時Proxy server(代理伺服器)就非常重要,Proxy server會記錄底下所有node的IP,當request經過時,Proxy server會將你的request轉發到對應的IP。而你不需要知道中間到底經過了多少Proxy server就可以存取目標IP,這就是所謂的Forward Proxy(正向代理)。
而User在發送request給server時,他的目標是存取資料,而不是server的位置。因此為了保護App server不受攻擊,通常會在最外層架設Web server,Web server會將request依照設定轉發到不同的App server,App server處理完後也會透過Web server再返回給User,如此User既不知道App server的真實位置也能存取資料,這就是Reverse Proxy(反向代理)。
Web server(Load Balance)
我不能用用一台App server取代Web server的功用嗎?
舉例來說,之前我們的部署將像是一個私廚(App server)處理每一個客人(User)的客製化的餐點(request),但也是有很多人客人只是要一個簡易的微波食品(靜態資源),如果你的前台服務生(Web server)可以快速處理並送餐(response),就不會導致你的私廚要料理又要微波的窘境,且客人也能更快收到餐點。當然Flask也能處理,只是Nginx表現更好👍🏻
Web server To many App server
如上述所說,當你的App server增加時,Nginx也能有效率的分配request給每一個App server(Load Balance),一切取決於你的設定。Nginx分配App server模式可以設定成:
- round-robin(輪詢):將request依序分配到App server,也是Nginx預設的模式。
- weight round-robin(權重):將App server設定weight,設定越大則分配越多request。性能越強的App server可以適時提高weight來平衡。
- least-connected(最少連線):分配request給當前最少連線的App server。
- IP-hash:將request的IP透過hash table紀錄在冊,讓相同IP再次發送request時連線到相同的App server。若App server有存取User的session(e.g. 儲存購物車),可使用此模式讓User每次連到相同App server。
結論
- 使用Guicorm部署Flask,彌補Flask原生開發server效能不足。
- 瞭解WSGI server作用。
- Web server可以有效的分配request給App server。(Load Balance)
- Web server可以隱藏App server的位置(Reverse Proxy)
- 如何適當部署server。