Docker之路(三)docker安装nginx实现对springboot项目的负载均衡

news2024/12/23 7:23:20

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")
    @ResponseBody
    public 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镜像

  1. 修改项目为三个不同的端口分别打包,然后上传的linux,目录如下:

    	drwxr-xr-x. 2 root root       54 529 10:36 config
    	-rw-r--r--. 1 root root      133 529 10:36 Dockerfile
    	-rw-r--r--. 1 root root     7172 65 2024 jenkinsTest8182.jar
    	-rw-r--r--. 1 root root     7172 65 2024 jenkinsTest8183.jar
    	-rw-r--r--. 1 root root     7145 57 17:11 jenkinsTest.jar
    	drwxr-xr-x. 2 root root     4096 57 16:49 lib
    
  2. 我这里用的是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"]
    
  3. 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
    
  4. 运行这三个项目的镜像

    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并且启动

  1. 启动前,需要将nginx的配置挂载一份到宿主机上,这样方便我们修改,而不用每次都进入容器去修改,因为容器里面vim这些指令是没有的。挂载的参数是-v(简易版)或者-mount(复杂版),这两个参数都可已实现挂载,我们后面再讨论,这里使用的是-v。

  2. -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.conf
      docker cp mynginx:/etc/nginx/conf.d/default.conf /home/docker-nginx/default.conf
    

    注意,这里容器启动才能copy,所以要不你先不挂载启动一个容器copy,要不就去搜一下默认的文件是啥(文章后面我会贴出来)。

  3. 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
    
  4. 访问nginx看是否成功
    在这里插入图片描述

  5. 修改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默认的轮询策略,关于这点,我们会在后面详细讲解。

  6. 重启nginx容器查看是否实现了负载均衡

    docker container restart mynginx
    

    浏览器访问同一个URL,看看是否会负载均衡
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    这里可以看到,我请求了三次,分别返回了三个结果,然后再请求又从第一个返回,证明了我们的轮询策略是成功了的。

六、nginx的负载均衡策略

以下配置均采用本文的集群案例,介绍三种常用的。

  1. 轮询策略
    默认的策略,不需要额外配置,本文就使用默认的配置。
  2. 权重策略
    可以为某些服务器添加权重,让该服务器更多的为用户提供服务,后面添加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;
    }
    
  3. 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的常用属性

  1. down属性,标记不可用,这样就不会像这个服务器分发请求。
	upstream demo1 {
	    server 172.16.72.128:8181 down;
	    server 172.16.72.128:8182;
	    server 172.16.72.128:8183;
	}
  1. BACKUP 备用机设置,正常情况下该服务器不会被访问.当主机全部宕机或者主机遇忙时,该服务器才会访问.
	upstream demo1 {
	    server 172.16.72.128:8181 down;
	    server 172.16.72.128:8182 backup;
	    server 172.16.72.128:8183;
	}
  1. 宕机服务器高可用实现
    当服务器宕机时,如果访问的失败达到最大失败次数,则自动标识为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之路第四期见。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1806755.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【leetcode--盛水最多的容器】

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 写出来了一半,想到用双指针&am…

大数据数仓的数据回溯

在大数据领域,数据回溯是一项至关重要的任务,它涉及到对历史数据的重新处理以确保数据的准确性和一致性。 数据回溯的定义与重要性 数据回溯,也称为数据补全,是指在数据模型迭代或新模型上线后,对历史数据进行重新处理…

VisionPro的应用和入门教程

第1章 关于VisionPro 1.1 康耐视的核心技术 1. 先进的视觉系统 康耐视的视觉系统结合了高性能的图像传感器、复杂的算法和强大的计算能力,能够实时捕捉、分析和处理高分辨率图像。其视觉系统包括固定式和手持式两种,适用于各种工业环境。无论是精密电…

centos7安装字体

1.安装命令 yum install fontconfig #字体库命令 yum install mkfontscale #更新字体命令2.安装字体(注意权限问题) 进入目录 /usr/share/fonts ,该目录是 centos7 字体库的默认安装目录。在该目录下创建一个文件夹 ekp (名字…

C++从入门到精通(最详细教程,12万总结,带你掌握c++知识,涵盖大量知识点)

目录 一、面向对象的思想 二、类的使用 1.类的构成 2.类的设计 三、对象的基本使用 四、类的构造函数 1.构造函数的作用 2.构造函数的特点 3.默认构造函数 3.1.合成的默认构造函数 3.2.手动定义的默认构造函数 四、自定义的重载构造函数 五、拷贝构造函数 1.手动…

312. 戳气球 Hard

有 n 个气球,编号为0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中。 现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i 1] 枚硬币。 这里的 i - 1 和 i 1 代表和 i 相邻…

设计模式之观察者模式ObserverPattern(十一)

一、概述 观察者模式 (Observer Pattern) 是一种行为型设计模式,又被称为发布-订阅 (Publish/Subscribe) 模式,它定义了对象之间的一种一对多的依赖关系,使得当一个对象的状态发生变化时,所有依赖于它的对象都会自动收到通知并更新…

Sui Generis如何为艺术家弥合Web3的鸿沟

Sui Generis是一家于3月推出的NFT拍卖行,其联合创始人兼CEO Gab9说其愿景是——更好、更大、更强! 表面上看,Sui Generis是备受欢迎的Tombheads NFT拍卖行的重新品牌化,该拍卖行今年早些时候从Fantom区块链迁移出来。但它于3月31…

Ajax 快速入门

Ajax 概念:Ajax是一种Web开发技术,允许在不重新加载整个页面的情况下,与服务器交换数据并更新网页的部分内容。 作用: 数据交换:Ajax允许通过JavaScript向服务器发送请求,并能够接收服务器响应的数据。 异…

从GAN到WGAN(01/2)

从GAN到WGAN 文章目录 一、说明二、Kullback-Leibler 和 Jensen-Shannon 背离三、生成对抗网络 (GAN)四、D 的最优值是多少?五、什么是全局最优?六、损失函数代表什么?七、GAN中的问题 一、说明 生成对抗网络 &#…

开源项目学习——vnote

一、介绍 vnote是一款免费且开源的markdown编辑器,用C开发,基于Qt框架,windows/linux/mac都能用。 二、编译 $ git clone --recursive https://github.com/vnotex/vnote.git $ cd vnote && mkdir build $ cd build $ cmake ../ $ …

【端午安康,给大家讲个“网络”故事,深刻一下!】

牛马我🐴上周又挨锤了, 网络是不稳定的,博学多知的你可能知道,可能不知道。但假如没亲身经历过,知不知道都不深刻,牛马踩了个网络的坑,深刻了,这里分享下, 一个真相 无…

【算法训练记录——Day27】

Day27——回溯算法Ⅲ 1.组合总和2.组合总和II3.分割回文串 内容 ● 39.组合总和 ● 40.组合总和II ● 131.分割回文串 1.组合总和 思路&#xff1a;和组合总和一样&#xff0c;先从candidates中遍历选择元素&#xff0c;但是纵向递归时所选择元素要包括当前元素 vector<int&…

289M→259M得物包体积治理实践

一、前言 iOS应用的包体积大小是衡量得物性能的重要指标&#xff0c;过大包体积会降低用户对应用的下载意愿&#xff0c;还会增加用户的下载等待时间以及用户手机的存储空间&#xff0c;本文重点介绍在包体积治理中的新思路以及原理与实践。 二、原理介绍 Macho产物测试 我…

什么是档案数字化管理

档案数字化管理指的是将传统的纸质档案转换为数字形式&#xff0c;并通过电子设备、软件和网络技术进行管理和存储的过程。 档案数字化管理包括以下几个步骤&#xff1a; 1. 扫描和数字化&#xff1a;将纸质档案通过扫描仪转换为数字图像或文档。可以使用OCR&#xff08;光学字…

AI论文速读 | 2024[ICML]FlashST:简单通用的流量预测提示微调框架

题目&#xff1a; FlashST: A Simple and Universal Prompt-Tuning Framework for Traffic Prediction 作者&#xff1a;Zhonghang Li, Lianghao Xia&#xff08;夏良昊&#xff09;, Yong Xu&#xff08;徐勇&#xff09;, Chao Huang 机构&#xff1a;华南理工大学&#xf…

搜索与图论:深度优先搜索

搜索与图论&#xff1a;深度优先搜索 题目描述参考代码 题目描述 参考代码 #include <iostream>using namespace std;const int N 10;int n; int path[N]; bool st[N];void dfs(int u) {// u n 搜索到最后一层if (u n){for (int i 0; i < n; i) printf("%d …

C++ MPI多进程并发

下载 用法 mpiexec -n 8 $PROCESS_COUNT x64\Debug\$TARGET.exe 多进程并发启动 mpiexec -f hosts.txt -n 3 $PROCESS_COUNT x64\Debug\$TARGET.exe 联机并发进程&#xff0c;其它联机电脑需在相同路径下有所有程序 //hosts.txt 192.168.86.16 192.168.86.123 192.168…

htb-linux-3-shocker

nmap web渗透 由于只有80端口&#xff0c;只考虑目录扫描和静态文件提醒 为什么能能知道http://10.10.10.56/cgi-bin/user.sh&#xff1f; 因为百度的 curl访问该文件 shell flag root

【C语言】轻松拿捏-联合体

谢谢观看&#xff01;希望以下内容帮助到了你&#xff0c;对你起到作用的话&#xff0c;可以一键三连加关注&#xff01;你们的支持是我更新地动力。 因作者水平有限&#xff0c;有错误还请指出&#xff0c;多多包涵&#xff0c;谢谢&#xff01; 联合体 一、联合体类型的声明二…