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 <[email protected]> #定义工作目录 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目录上。
参考博客:实战docker,构建nginx反向代理tomcat,学习link和docker-compose