Docker之路(三)docker+nginx+springboot负载均衡
- 前言:
- 一、安装docker
- 二、安装nginx
- 三、准备好我们的springboot项目
- 四、将springboot项目分别build成docker镜像
- 五、配置nginx并且启动
- 六、nginx的负载均衡策略
- 七、nginx的常用属性
- 八、总结
前言:
本文采用比较经典的方式来集成,如果想了解docker-compse方式的,请移步我的下篇文章。
一、安装docker
请参考我的这篇文章:Docker之路(一)–安装Docker
二、安装nginx
docker pull nginx
这个等同于docker pull nginx:latest,都是拉取最新的镜像版本。这里我们先不着急启动nginx,先把准备好的三个springboot项目准备好。
三、准备好我们的springboot项目
这里我用了同一个springboot项目,然后分了三个端口来打包,端口分别是8181,8182,8183,测试接口也是用的默认的,现在创建一个最新的springboot项目,会自动生成一个BaseController测试类。这里我们就用它这个默认的接口:/hello
@Controller
public class BasicController {// http://127.0.0.1:8181/hello?name=lisi@RequestMapping("/hello")@ResponseBodypublic String hello(@RequestParam(name = "name", defaultValue = "unknown user") String name) {return "Hello " + name;}
}
然后,我们分别将这个接口的返回值改一下,根据端口一一对应,这样后面nginx负载均衡的时候,我们就容易判断是否成功,具体负载到哪一个端口去了。
- 8181–> return "Hello " + name;
- 8182–> return “Hello 2” + name;
- 8183–> return “Hello 3” + name;
四、将springboot项目分别build成docker镜像
-
修改项目为三个不同的端口分别打包,然后上传的linux,目录如下:
drwxr-xr-x. 2 root root 54 5月 29 10:36 config-rw-r--r--. 1 root root 133 5月 29 10:36 Dockerfile-rw-r--r--. 1 root root 7172 6月 5 2024 jenkinsTest8182.jar-rw-r--r--. 1 root root 7172 6月 5 2024 jenkinsTest8183.jar-rw-r--r--. 1 root root 7145 5月 7 17:11 jenkinsTest.jardrwxr-xr-x. 2 root root 4096 5月 7 16:49 lib
-
我这里用的是maven-jar-plugin而不是springboot的maven打包插件,所以目录会有所不同,springboot的会整体打包,没有lib和config这个,这里按照你自己需要来就行。如何将jar包build成docker镜像,参考我这篇文章:Docker之路(二)–用Docker部署一个Web项目。
在本篇文章,我的Dockerfile是这样写的:如果你是springboot的打包插件,那么就只需要copy jar包为app.jar就行,不需要copy lib和config这个目录文件。FROM openjdk:11 VOLUME /tmp #这一步需要修改jenkinsTest.jar为三个不同的jar包名称 COPY jenkinsTest.jar app.jar #这里每次build我都会修改config下application.properties里面的端口 COPY config config COPY lib lib ENTRYPOINT ["java","-jar","/app.jar"]
-
build成功后看看我们的镜像:
[root@localhost docker-nginx]# docker images REPOSITORY TAG IMAGE ID CREATED SIZE 8183demo latest 483ecd3a7fff 49 minutes ago 714MB 8182demo latest c1fe57a09bc0 49 minutes ago 714MB 8181demo latest 3b76435d0f75 31 hours ago 714MB
-
运行这三个项目的镜像
docker run --name 8181demo -d -p 8181:8181 8181demo docker run --name 8182demo -d -p 8182:8182 8182demo docker run --name 8183demo -d -p 8183:8183 8183demo
然后看看浏览器能否访问
这里是看到是OK了的,然后就可以操作我们的nginx了。
五、配置nginx并且启动
-
启动前,需要将nginx的配置挂载一份到宿主机上,这样方便我们修改,而不用每次都进入容器去修改,因为容器里面vim这些指令是没有的。挂载的参数是-v(简易版)或者-mount(复杂版),这两个参数都可已实现挂载,我们后面再讨论,这里使用的是-v。
-
-v格式: -v [宿主机绝对路径]:[容器路径],
(1)这里我们在宿主机新建目录/home/docker-nginx,然后在将nginx默认的配置文件:nginx.conf和default.conf复制一份到/home/docker-nginx下面(这个目录最好新建,虽然可以自动生成,但是有时候会出麻烦,还有这两个文件,一定不能是空文件,不是你nginx容器启动不起来)。
(2)从容器中copy文件:docker cp [容器名字或者id]:容器路径 宿主机路径docker cp mynginx:/etc/nginx/nginx.conf /home/docker-nginx/nginx.confdocker cp mynginx:/etc/nginx/conf.d/default.conf /home/docker-nginx/default.conf
注意,这里容器启动才能copy,所以要不你先不挂载启动一个容器copy,要不就去搜一下默认的文件是啥(文章后面我会贴出来)。
-
ngnix完整的启动命令:挂载两个conf文件和一个log日志目录,然后映射ngnix端口为:30001
docker run --name mynginx \ -v /home/docker-nginx/nginx.conf:/etc/nginx/nginx.conf \ -v /home/docker-nginx/log:/var/log/nginx \ -v /home/docker-nginx/default.conf:/etc/nginx/conf.d/default.conf \ -d -p 30001:80 nginx
-
访问nginx看是否成功
-
修改nginx配置文件。
这里有两个文件,一个是nginx.conf和default.conf,这两者的关系是:nginx.conf包含了default.conf,这个很关键。
(1)修改nginx.conf:因为我们用的是三个项目的集群,这里我们先将集群配置加到nginx.conf里面,使用upstream标签,后面名字随便取,我这里是demo1。上面都有注释user nginx; worker_processes auto;error_log /var/log/nginx/error.log notice; 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;#nginx默认配置文件,本文本案例只添加了如下配置upstream demo1 {server 172.16.72.128:8181;server 172.16.72.128:8182;server 172.16.72.128:8183;}#这行就是上面所说的,这两个文件的包含关系,在这里引用include /etc/nginx/conf.d/*.conf; }
(2)修改default.conf,将我们定义的upstream demo1添加进location 标签里面去。
server {listen 80;listen [::]:80;server_name localhost;#access_log /var/log/nginx/host.access.log main;location / {#这行就是我们作的唯一修改proxy_pass http://demo1;# root /usr/share/nginx/html;# index index.html index.htm;}#error_page 404 /404.html;# redirect server error pages to the static page /50x.html#error_page 500 502 503 504 /50x.html;location = /50x.html {root /usr/share/nginx/html;}# proxy the PHP scripts to Apache listening on 127.0.0.1:80##location ~ \.php$ {# proxy_pass http://127.0.0.1;#}# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000##location ~ \.php$ {# root html;# fastcgi_pass 127.0.0.1:9000;# fastcgi_index index.php;# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;# include fastcgi_params;#}# deny access to .htaccess files, if Apache's document root# concurs with nginx's one##location ~ /\.ht {# deny all;#}}
负载均衡策略:我们什么都没有配置,用的是nginx默认的轮询策略,关于这点,我们会在后面详细讲解。
-
重启nginx容器查看是否实现了负载均衡
docker container restart mynginx
浏览器访问同一个URL,看看是否会负载均衡
这里可以看到,我请求了三次,分别返回了三个结果,然后再请求又从第一个返回,证明了我们的轮询策略是成功了的。
六、nginx的负载均衡策略
以下配置均采用本文的集群案例,介绍三种常用的。
- 轮询策略
默认的策略,不需要额外配置,本文就使用默认的配置。 - 权重策略
可以为某些服务器添加权重,让该服务器更多的为用户提供服务,后面添加weight字段就行。upstream demo1 {server 172.16.72.128:8181 weight=6;server 172.16.72.128:8182 weight=3;server 172.16.72.128:8183 weight=1; }
- IPHASH策略
同一个ip一只访问同一个服务器,缺点就是服务器炸了就没法分发请求。upstream demo1 {ip_hash;server 172.16.72.128:8181 weight=6;server 172.16.72.128:8182 weight=3;server 172.16.72.128:8183 weight=1; }
七、nginx的常用属性
- down属性,标记不可用,这样就不会像这个服务器分发请求。
upstream demo1 {server 172.16.72.128:8181 down;server 172.16.72.128:8182;server 172.16.72.128:8183;}
- BACKUP 备用机设置,正常情况下该服务器不会被访问.当主机全部宕机或者主机遇忙时,该服务器才会访问.
upstream demo1 {server 172.16.72.128:8181 down;server 172.16.72.128:8182 backup;server 172.16.72.128:8183;}
- 宕机服务器高可用实现
当服务器宕机时,如果访问的失败达到最大失败次数,则自动标识为down,在一定的周期之内,如果服务器恢复正常,则还会尝试访问故障机。
max_fails=10 最大的失败次数
fail_timeout=60s; 设定周期为60秒
upstream demo1 {server 172.16.72.128:8181 max_fails=10 fail_timeout=60s;server 172.16.72.128:8182 max_fails=10 fail_timeout=60s;server 172.16.72.128:8183 max_fails=10 fail_timeout=60s;}
八、总结
以上就是本次文章全部内容了,都是比较简单和基础的操作,但是一些细节没注意还是容易出现问题,欢迎评论区讨论和错误纠正,我们Docker之路第四期见。