Nginx實現負載均衡是通過配置nginx.conf來實現的,nginx.conf的全部內容如下:
user nginx; worker_processes 1; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; #tcp_nopush on; keepalive_timeout 65; #gzip on; #include /etc/nginx/conf.d/*.conf; upstream tomcat_client { server t01:8080 weight=1; server t02:8080 weight=1; } server { server_name ""; listen 80 default_server; listen [::]:80 default_server ipv6only=on; location / { proxy_pass http://tomcat_client; proxy_redirect default; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } }
可以看到,通過server節點的配置實現了監聽80端口,“proxy_pass http://tomcat_client;“表示對請求的處理交給了tomcat_client,而tomcat_client的具體配置:
upstream tomcat_client { server t01:8080 weight=1; server t02:8080 weight=1; }
即交給了url為t01:8080和t02:8080這兩個server,並且每個server處理的權重都是1。(t01:8080和t02:8080是個別名,和link參數中的別名對應)
nginx的配置就這些了,接下來我們看看如何制作nginx的鏡像文件,也就是Dockerfile的具體內容:
# First docker file from lz # VERSION 0.0.1 # Author: lz #基礎鏡像 FROM nginx #作者 MAINTAINER Lizhong <1979158178@qq.com> #定義工作目錄 ENV WORK_PATH /etc/nginx #定義conf文件名 ENV CONF_FILE_NAME nginx.conf #刪除原有配置文件 RUN rm $WORK_PATH/$CONF_FILE_NAME #復制新的配置文件 COPY ./$CONF_FILE_NAME $WORK_PATH/ #給shell文件賦讀權限 RUN chmod a+r $WORK_PATH/$CONF_FILE_NAME
如上所示,Dockerfile文件非常簡單,就是把原有系統中的nginx.conf文件刪掉,換成我們剛才自己做的文件就行了。
現在我們新建個目錄image_nginx,這個目錄下只有兩個文件,nginx.conf和Dockerfile,如下圖:

打開終端,進入此目錄,執行命令行:
docker build -t nginx:0.0.1 .
執行完畢后,再執行docker images,就能看到新的鏡像文件了,如下圖:

對於tomcat的鏡像,請直接使用上一篇文章《實戰docker,編寫Dockerfile定制tomcat8鏡像,實現web應用在線部署》中通過Makefile定制的tomcat鏡像,這個鏡像的好處是:部署完畢后驗證負載均衡能力時,可以通過maven插件直接給tomcat容器部署應用包。
現在我們有了nginx和tomcat的鏡像,接下來要做的就是run一個nginx容器,再run兩個tomcat容器,來實現負載均衡,run這三個容器可以有如下兩種方式來實現:
1. 執行三個docker run命令,啟動三個容器;
2. 使用docker compose來實現批量啟動多個容器;
我們先來試試第一種方式吧:
1. 啟動第一個tomcat容器,起名tomcat001,在終端輸入:
docker run --name=tomcat001 -p 8081:8080 -e TOMCAT_SERVER_ID=tomcat_server_001 -idt tomcat:0.0.1
2.啟動第二個tomcat容器,起名tomcat002,在終端輸入:
docker run --name=tomcat002 -p 8082:8080 -e TOMCAT_SERVER_ID=tomcat_server_002 -idt tomcat:0.0.1
3.這時候執行docker ps就能看到已經有兩個容器啟動了,兩個tomcat容器各自暴露了自己的8080端口,然后分別映射到了當前電腦的8081和8082兩個端口,也就是說我們訪問192.168.1.129:8081以及192.168.1.129:8082就能訪問到兩個容器上的tomcat了,打開瀏覽器試試;
通過maven部署war包到tomcat上去,修改pom.xml中的參數,如下圖:

將上圖紅框中的端口改為8081后,在pom.xml所在目錄下執行:
mvn clean package -U -Dmaven.test.skip=true tomcat7:redeploy
然后再將端口改為8082再執行同樣的命令,這樣就能把war包分別部署到兩個tomcat容器上了,這時候用瀏覽器訪問http://192.168.1.129:8081/loadbalancedemo/hello就能看到下圖效果:

訪問http://192.168.1.129:8082/loadbalancedemo/hello的效果如下:

在終端輸入以下命令,啟動nginx:
docker run --name=ngx001 --link=tomcat001:t01 --link=tomcat002:t02 -p 80:80 -idt nginx:0.0.1
這里重點看一下參數–link=tomcat001:t01,–link表示當前命令啟動的容器ngx001要和另一個名叫tomcat001的容器建立連接,“tomcat001:t01“中的“t01“表示t01是連接建立后tomcat001的別名,或者可以理解為:ngx001啟動后,/etc/hosts文件中加入了一條記錄,ip是tomcat001的ip,name是t01。
我們輸入docke exec -it ngx001 /bin/bash登錄ngx001,再輸入cat /etc/hosts即可看到如下:
root@a4bedc55e938:/# cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 172.18.0.2 t01 c4gfhf5hjmfd tomcat001 172.18.0.3 t02 f34d4563sd6j tomcat002 172.18.0.4 a4bedc55e938
也就是說,在ngx001容器內部,所有訪問t01的地方,實際上都訪問的是tomcat001對應的ip,搞清楚了這一點,再看看之前配置的nginx的nginx.conf文件:
upstream tomcat_client { server t01:8080 weight=1; server t02:8080 weight=1; }
這里面的t01,t02和link參數中的t01,t02對應,這樣nginx在用t01做為域名做請求轉發的時候,請求就能到tomcat001和tomcat002上了。
此時通過瀏覽器多次訪問http://192.168.1.129/loadbalancedemo/hello就可以看到請求分發到了不同的tomcat上:

進行到這里,我們已經實現了nginx+tomcat實現負載均衡的效果,但是啟動三個容器要執行三次命令似乎挺麻煩,有沒有什么批量執行的方法呢?自己寫shell,把所有命令都放在里面。但是其他的批量操作呢?比如停止,恢復,構建鏡像,查看信息等,所以使用compose是個更好的選擇,compose是用於定義和運行復雜Docker應用的工具,可以批量的處理多個容器。
直接上代碼,新建一個docker-compose.yml文件,內容如下:
version: '2' services: nginx001: image: nginx:0.0.1 links: - tomcat001:t01 - tomcat002:t02 ports: - "80:80" restart: always tomcat001: image: tomcat:0.0.1 ports: - "8081:8080" environment: TOMCAT_SERVER_ID: tomcat_server_001 restart: always tomcat002: image: tomcat:0.0.1 ports: - "8082:8080" environment: TOMCAT_SERVER_ID: tomcat_server_002 restart: always
每個容器都定義成一個節點,節點內有具體的參數鍵值對,我們之前docker run帶上的那些參數都在里面了。
現在可以嘗試一下執行docker-compose.yml了,在執行之前請先執行如下的命令,將我們前面啟動的三個容器先停止再刪除:
docker stop tomcat001 tomcat002 ngx001;docker rm tomcat001 tomcat002 ngx001
然后進入docker-compose.yml文件所在的目錄,執行如下命令:
docker-compose up -d
執行完畢后,再執行docker ps查看當前容器信息:

容器已經一次性啟動起來了,不過名字似乎變了,被加了前綴,這個前綴的具體內容和當前目錄有關,現在瀏覽器里面輸入192.168.1.129就能順利打開tomcat的歡迎頁;
參照之前的方式通過”mvn clean package -U -Dmaven.test.skip=true tomcat7:redeploy”命令將war包分別部署在兩個tomcat上,再訪問“http://192.168.1.129/loadbalancedemo/hello“來驗證nginx是否將請求分發到了不同的tomcat上。
以上就是利用link和docker compose部署server負載均衡的實戰了,就是每次部署war包很麻煩,其實除了這種方式,我們還可以制作tomcat的鏡像的時候,在Dockerfile中寫命令將war包復制到鏡像中去,也可以Docker run的時候通過-v參數掛載當前電腦的實際目錄到tomcat的webapps目錄上。
