1. 程式人生 > >把AspDotNetCoreMvc程序運行在Docker上-part4:實現負載均衡

把AspDotNetCoreMvc程序運行在Docker上-part4:實現負載均衡

dash run ner 網絡 endpoint width idg 識別 nginx

在上一part《把AspDotNetCoreMvc程序運行在Docker上-part3:使用獨立的存儲容器》,我們利用MySql容器和Volume實現了真正意義上的數據存儲。整個結構非常簡單,就是一個web容器和一個數據庫容器,是一個簡單的應用。如今都流行支持高並發,集群什麽的,最起碼要有多個web服務器,於是通常要用到負載均衡的技術,比如HAproxy,Nginx等等。那麽這一部分,我們接著用Docker技術實現負載均衡,其實說嚴格還是用的老技術,只不過包裝到了Docker容器中而已。

自定義網絡配置

docker內置了默認的網絡配置,默認的網絡配置是自動創建好的,可用於容器之間的網絡訪問。在上一part中的我們就用到了這個默認的網絡配置,裏面的MySql容器就是通過默認網絡配置訪問的。

通過以下命令可以查看docker默認創建的網絡配置

docker network ls

NETWORK ID NAME DRIVER SCOPE
13d5e19c447e bridge bridge local
fb4ce1a7bfcf host host local
ee50b1dc443b none null local

在創建了MySql容器之後,系統分配的網絡是bridge,我們可以通過以下命令查看bridge被哪個容器使用

"Containers": {
"d4e5cf975ad5e3ff11620c02f9b626fa4d0042faab83fa9d0ea86801d2cce452": {
"Name": "mysql",
"EndpointID": "5fe1c90310938704323ba4cbb7c156a962ca07cd49845d12ea142dff40021212",
"MacAddress": "02:42:ac:11:00:02",

"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},

從Containers節點能看到當前在使用該網絡配置的容器以及分配的IP地址,通過這個IP就能訪問到該容器。

這麽看來默認網絡配置似乎夠用,但是它有他的局限性。首先這個IP是docker分配的,需要手動去查看用的是哪個IP地址。另外一個重要問題就是,如果有多個容器都使用了同一個網絡,沒法根據功能進行區分和管理,尤其是後續我們要講到的負載均衡功能,用自定義的網絡配置更加靈活。

創建自定義網絡配置

通過以下命令創建frontend和backend兩個自定義網絡,名字可以改成其他。

docker network create frontend

docker network create backend

frontend將用於我們的網站容器,backend將用於MySql容器。

查看已創建的網絡

docker network ls

NETWORK ID NAME DRIVER SCOPE
f18bd38d350f backend bridge local
13d5e19c447e bridge bridge local
1318f2d56587 frontend bridge local
fb4ce1a7bfcf host host local
ee50b1dc443b none null local

有了自定義網絡之後,就可以將它分配給容器

為了便於演示,首先通過如下命令刪除之前創建的容器

docker rm -f $(docker ps -aq)

創建MySql容器,並指定使用backend網絡

docker run -p 3306:3306 -d --name mysql -v productdata:/var/lib/mysql --network=backend -e MYSQL_ROOT_PASSWORD=password -e bind-address=0.0.0.0 mysql:8.0.0

相比上一part,這裏只是多了一個—network參數

使用自定義網絡的還有一個很有用的功能就是,在docker內部可以通過容器的名稱作為網絡訪問地址,比如我們這裏創建了MySql容器,容器名是mysql,那麽實際上在docker內部,mysql就可以作為host名稱,然後docker內部會將mysql解析為其分配的IP地址。這樣的話,我們在docker內部就可以直接用容器名稱來配置網絡參數,比如數據庫的主機地址,接下來我們創建站點容器將使用到。

創建MVC網站容器

還是使用之前我們定義的鏡像shenba/aspdotnetcoremvc

這裏我們創建三個容器

docker create --name app1 -e DBHOST=mysql -e MESSAGE="1st Server" --network backend shenba/aspdotnetcoremvc

docker create --name app2 -e DBHOST=mysql -e MESSAGE="2nd Server" --network backend shenba/aspdotnetcoremvc

docker create --name app3 -e DBHOST=mysql -e MESSAGE="3rd Server" --network backend shenba/aspdotnetcoremvc

這裏的創建命令只是MESSAGE不同,這個MESSAGE是個環境變量,會作為網站內容輸出,用於識別目前是在哪個容器中。

這裏的network的參數指定方式跟創建MySql容器的不同,這裏只是指定需要連接這個網絡,這三個容器都需要連接backend網絡訪問mysql容器。

此外,這裏創建的時沒有指定宿主機的端口映射。

我們需要進一步將這三個容器連接到frontend網絡,然後通過frontend網絡訪問這三個容器。

連接到frontend網絡

docker network connect frontend app1

docker network connect frontend app2

docker network connect frontend app3

啟動這三個MVC站點容器

docker start app1 app2 app3

使用HAProxy容器

啟動完三個MVC網站容器之後,還不能被宿主機訪問到,因為沒有公開外網訪問的IP和端口,所以它們只能被docker內部的網絡訪問到。這就是我們通常使用負載均衡的場景,應用服務器都部署在內網,然後外部通過反向代理的方式訪問到內部的應用服務器。所以接下來我們需要一個反向代理的服務器,在docker裏當然就是一個安裝了反向代理服務的容器。

我們使用HAPoxy容器來實現負載均衡,首先在docker所在的服務器(或者說是宿主機,這裏用的是centos)創建一個haproxy.cfg配置文件

defaults
timeout connect 5000
timeout client 50000
timeout server 50000

frontend localnodes
bind *:80
mode http
default_backend mvc

backend mvc
mode http
balance roundrobin
server mvc1 app1:80
server mvc2 app2:80
server mvc3 app3:80

簡單的說就是將負載均衡服務器的80端口公開,並且將這個端口的請求分配到三個不同的MVC站點中。

接下來在cfg文件所在的目錄執行如下命令

docker run -d --name loadbalancer --network frontend -v "$(pwd)/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg" -p 3000:80 haproxy:1.7.0

參數跟創建其他容器一樣,提供了名稱(loadbalancer),網絡(frontend),端口映射(3000:80),基於鏡像(haproxy:1.7.0)

比較特別的是-v參數,這裏是將宿主機的haproxy.cfg映射到了容器裏的haproxy.cfg文件。

好了到此,實現負載均衡的所有配置已經完成,打開瀏覽器輸入http://192.168.115.136:3000,重復刷新多次那麽會看到網站的內容標題會發生變化,比如截圖所示

技術分享

目前的結構圖如下

技術分享



把AspDotNetCoreMvc程序運行在Docker上-part4:實現負載均衡