docker-django-nginx-uwsgi-postgres-load-balance-tutorial
實戰 Docker + Django + Nginx + uWSGI + Postgres - Load Balance 📝
這篇文章主要接續上一篇
繼續介紹,這次的重點會放在 Nginx 的 Load Balance 上
- Youtube Tutorial PART 1 - 正向代理器 VS 反向代理器 - 簡介
- Youtube Tutorial PART 2 - Docker + Django + Nginx + Load Balance - 概念
- Youtube Tutorial PART 3 - Docker + Django + Nginx + Load Balance - 實戰
- Youtube Tutorial PART 4 - Django + Nginx + Load Balance - Docker scale
簡介
在開始介紹 Nginx 的 Load Balance 之前,我會先帶大家了解一些名詞。
還記得在 上一篇 教學中,提到 Nginx 可以設定 反向代理器 嗎?
那時候沒有詳細解釋什麼是 反向代理器 ,這邊我將先帶大家了解
正向代理器 以及 反向代理器 的差別
正向代理器 VS 反向代理器
正向代理器
正向代理器是一個位於使用者端以及目標 Server 之間的 代理伺服器 ( Proxy Server ),
透過代理伺服器收發 Request / Respond 資料,
如上圖,X 無法直接和 Z 請求資料,但是 Y 可以和 Z 請求資料 ( 於是 X 透過 Y 向 Z 請求資料 ),
Y 得到資料後,再將資料回傳給 X,這樣 X 就能順利得到 Z 的資料了 。
通常正向代理器必須額外做一些設定才可以使用。
正向代理器,Client 和 Proxy 可視為同一個 LAN ,對 Server 是隱藏的。
溫馨小提醒
-
LAN ( Local Area Network ),又稱 區域網路
-
WAN ( Wide Area Network ),又稱 廣域網路
-
WLAN ( Wireless LAN ),又稱 無線區域網路
正向代理器是代理使用者端( Client 端 ),替使用者端( Client 端 )收發 Request / Respond,
讓真正的使用者對伺服器端( Server 端 )隱藏。
可能你自己也有使用過( 或正在使用
今天主角是阿鬼,阿鬼無法瀏覽 FB,但可以瀏覽 Server A,而阿鬼發現 Server A 可以訪問 FB,
於是阿鬼就透過 Server A 去瀏覽 FB,整個流程是,阿鬼透過 Server A 去瀏覽 FB,Server A 收到
來自阿鬼的 Request 時,去瀏覽 FB,FB 再把 Response 回傳給 Server A,Server A 再把收到的
Response 回傳給阿鬼,這樣阿鬼就能順利得到 FB 的資料,這就是透過 Proxy ( 正向代理器 )。
反向代理器
反向代理器則相反過來,對於使用者端來說,反向代理器就好像是目標 Server,
使用者端也不需要做額外的設定,
如上圖,雖然整個流程還是 X->Y->Z,但因為不用特別設定,所以使用者端會感覺好像直接是 X->Z,
反向代理器,Proxy 和 Server 屬於一個 LAN,對 Client 隱藏
反向代理器是代理伺服器端( Server 端 ),替伺服器端( Server 端 )收發 Request / Respond,
讓真正的伺服器( Server 端 )對使用者隱藏。
本次的主角 Load Balance 就是反向代理器的一種應用
教學
解釋了那麼多,我們要開始實戰 Nginx 的 Load Balance,範例一樣是使用 上一篇 做修改,
因為要做 Load Balance,所以增加一台主機( service ),名稱命名為 api2,基本上內容
都和 api 差不多,只是修改了一些名稱( 方便區別而已 ),可參考 docker-compose.yml。
整體的 Load Balance 的概念可以參考下圖
這樣有什麼好處呢 ?
最直接的好處就是,如果一台掛了,整個系統還是不會死,
因為其他的 Server 還是正常工作
再來就是我們的主角 my_nginx.conf,其實主要也是修改這邊的設定而已 😆
# the upstream component nginx needs to connect to
upstream uwsgi {
# server api:8001; # use TCP
server unix:/docker_api/app.sock weight=4 ; # for a file socket
server unix:/docker_api2/app2.sock weight=6; # for a file socket
}
# configuration of the server
server {
# the port your site will be served on
listen 80;
# index index.html;
# the domain name it will serve for
# substitute your machine's IP address or FQDN
server_name twtrubiks.com www.twtrubiks.com;
charset utf-8;
client_max_body_size 75M; # adjust to taste
# Django media
# location /media {
# alias /docker_api/static/media; # your Django project's media files - amend as required
# }
location /static {
alias /docker_api/static; # your Django project's static files - amend as required
}
location / {
uwsgi_pass uwsgi;
include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
}
}
其實設定並不難,只是在 upstream
裡面增加一台 Server 而已,後面的 weight
則代表權重,
Nginx 預設會使用 round-robin 演算法來實作 Load balance。
Load balancing methods
Nginx 主要的 Load balance 有三種
round-robin — requests to the application servers are distributed in a round-robin fashion
使用輪詢的方式,也可以加上 weight
權重,讓比較強的 Server 承受比較大的壓力( weight
設定高一點)。
least-connected — next request is assigned to the server with the least number of active connections
此種方式,Nginx 會將請求給負載 Loading 較輕的 Server,避免負載(A Server) Loading 已經很大了,
還將請求交給 A Server 處理。
ip-hash — a hash-function is used to determine what server should be selected for the next request (based on the client's IP address)
不管是 round-robin 還是 least-connected 的 Load balance ,每個 User 送出的請求都可能會被分到不同的
Server,並不能保證同一個 User 每次的請求都一定會連到同一台 Server, 因為這個原因,於是有了 ip-hash,
透過這個方法,會使用 ip 的方式將同一個 User 的請求都導到同一台
Server (除非這台 Server 掛了
介紹完了 Nginx 主要的三種 Load balance 演算法,至於要使用哪一種,就看你自己的需求了
更多範例以及詳細的說明可參考官網
( 建議閱讀 ,雖然我有幫大家整理重點出來了
http://nginx.org/en/docs/http/load_balancing.html
執行步驟
直接執行 docker-compose up
見證奇蹟
細部的圖就不再貼一次了,請參考 上一篇
會發現我們多了一台 api2
接著開啟另一個 terminal,進入 api
( Django + uWSGI ) 的容器,
指令可參考之前的 docker-tutorial-指令介紹,
docker exec -it <Container ID> bash
執行 migrate
python manage.py makemigrations musics
python manage.py migrate
建立 user
python manage.py createsuperuser
最後再執行
python manage.py collectstatic
將 Django 中的 static files 收集起來,變成 static folder,
我們不需要再進入 api2
的 container 執行剛剛的動作,因為我們都是連同一個 db,
到這裡基本上就是完工了
瀏覽 http://localhost:8080/api/music/ 確認是否正常。
執行畫面
瀏覽 http://localhost:8080/api/music/
那要怎麼確定真的有 Load balance 呢?
可以在頁面上瘋狂點擊 F5,然後我們觀察 terminal,你會發現
有時候是 api
,有時候是 api2
,還記得前面設定的 weight
權重,
api
和 api2
是 4:6,4:6 是什麼意思呢
假如現在有 10 個 Request 進來,4 個 Request 會交給 api
這個 Server 處理,
而剩下的 6 個 Request 則會交給 api2
這個 Server 處理 👍
weight
權重可以依照自己的需求設定。
接著再來模擬一台 Server 掛了的時候,如下圖,Server 因為某種原因掛了,
先透過 stop 指令將 api
container 停止
( 模擬 api
這台 Server 掛了 )
docker stop [OPTIONS] CONTAINER [CONTAINER...]
然後再繼續瀏覽 http://localhost:8080/api/music/,你會發現網站正常 work ( 確實沒有掛掉 ),
而且 terminal 現在都只會輸出 api2
,
因為我們已經將 api
停止了(模擬機器意外掛了),
有沒有很酷
範例是總共有兩台 server ( api
以及 api2
), 你也可以自己多新增幾台來玩玩看。
其他的負載平衡
除了 Nginx 的 Load banlance 之外,假設你的系統更龐大且有規模,
可以考慮使用更專業的負載平衡,像是 HAProxy ( High Availability Proxy ) ,
如果要專注在 Load banlance 上,選擇 HAProxy 應該會比 Nginx 的
Load banlance 還來的好。
如果對 HAProxy 有興趣,可參考 Docker Swarm + HAProxy
後記:
這次主要介紹了 Nginx 的 Load Banlance 給大家,建議大家可以動手玩玩看,整體會比較有感覺 😃
這次嘗試參考網路上的圖自己簡單的畫一遍,希望對大家多多少少有幫助😳
如果有在玩像是 AWS 的人,可以知道還有一種東西更狂,就是 異地同步備份,大家有興趣自行研究
如果有任何講錯的地方,請麻煩大家和我說,我會再修改,感謝各位的閱讀
下一步可以試試看用 Docker scale 的方法來完成( 更好的寫法 ),可參考 better 分支。
如果意猶未盡,延伸閱讀
執行環境
- Mac
- Python 3.6.2
- windows 10
Reference
Donation
文章都是我自己研究內化後原創,如果有幫助到您,也想鼓勵我的話,歡迎請我喝一杯咖啡
License
MIT license