【微服务】SpringBoot + Docker 实现微服务容器多节点负载均衡详解

目录

一、前言

二、前置准备

2.1 基本环境

2.2 准备一个springboot工程

2.2.1 准备几个测试接口

2.3 准备Dockerfile文件

2.4 打包上传到服务器

三、制作微服务镜像与运行服务镜像

3.1 拷贝Dockerfile文件到服务器

3.2 制作服务镜像

3.3 启动镜像服务

3.4 访问一下服务接口

四、配置负载均衡

4.1 源码包方式安装nginx

4.1.1 下载nginx安装包

4.1.2 解压安装包

4.1.3 进入解压后的安装包目录

4.1.4 编译安装

4.1.5 启动nginx

4.1.6 检查nginx服务是否启动成功

4.1.7 访问nginx主页

4.1.8 nginx其他命令补充

4.2 启动另外两个微服务容器

4.3 配置负载均衡

4.3.1 配置nginx负载均衡

4.3.2 负载均衡效果验证

4.4 固定微服务容器IP的方式配置负载均衡

4.4.1 创建一个docker网络

4.4.2 使用指定IP的方式启动三个微服务容器

4.4.3 测试访问服务接口

4.4.4 配置nginx负载均衡

4.5 使用Docker Compose配置负载均衡

4.5.1 创建docker网络

4.5.2 创建nginx.conf配置文件

4.5.3 创建docker-compose文件

4.5.4 启动容器

五、写在文末


一、前言

基于容器化部署微服务的实施方案目前在很多团队中实践应用,得益于docker 领域解决方案的完善,生态和组件的丰富,以及k8s的盛行,于是微服务接入docker进行部署也成为一种比较主流的方式,不过一旦项目上线,高可用问题在任何一个系统中都是需要亟待解决的,使用docker部署springboot也不例外,在不引入k8s的情况下,如何低成本的快速实现docker微服务多节点扩容呢,本篇将详细介绍一下。

二、前置准备

在正式开始操作之前,你需要提前做下面几项准备,以确保后面的部署、实施和相关的操作能够顺利完成。

2.1 基本环境

  • 云服务器或虚拟机,最低,2C4G;
  • 服务器安装了Docker环境,以及Docker Compose环境;
  • 本地JDK(JDK17),Maven,Idea等;

2.2 准备一个springboot工程

如下在本地创建一个springboot工程

2.2.1 准备几个测试接口

方便后面的测试效果

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class DockerController {//localhost:8081/test@GetMapping("/test")public String test(){return "docker test";}}

本地启动之后,确保接口能够正常调用

2.3 准备Dockerfile文件

在resources目录下添加一个Dockerfile文件,内容如下:

FROM  openjdk:17-jdk-alpine
ADD ./boot-docker.jar /app/boot-docker.jar
ENTRYPOINT ["java", "-jar", "/app/boot-docker.jar"]

2.4 打包上传到服务器

使用maven命令对上面的工程打包,将jar包上传到服务器目录

为了确保可用,使用java -jar命令启动一下

三、制作微服务镜像与运行服务镜像

使用docker的方式运行微服务,首先需要基于Dockerfile文件将原始的服务jar包制作成镜像,参考下面的操作过程

3.1 拷贝Dockerfile文件到服务器

在服务器目录与jar包同目录下,创建一个Dockerfile文件,将上述Dockerfile的内容拷贝进去

3.2 制作服务镜像

使用下面的命令,将本次的微服务jar包制作成docker镜像

  • 这里有个前提,需要服务器提前安装好docker compose组件,否则无法使用这个命令;

docker build -t boot-docker:1.0 .

执行成功后,通过docker imags命令检查微服务镜像是否生成

3.3 启动镜像服务

使用下面的命令启动第一个镜像服务

docker run -d -it -p 8081:8081 --name=boot-docker-1 boot-docker:1.0

3.4 访问一下服务接口

访问工程中预留的接口,看到如下效果,说明服务正常启动可用了

四、配置负载均衡

目前在项目中使用nginx作为路由转发,负载均衡的配置非常普遍,下面就以nginx为例进行说明。

4.1 源码包方式安装nginx

4.1.1 下载nginx安装包

使用下面的命令下载

wget http://nginx.org/download/nginx-1.20.2.tar.gz

4.1.2 解压安装包

执行下面的命令

tar -zxvf nginx-1.20.2.tar.gz -C /usr/local/src/

4.1.3 进入解压后的安装包目录

cd /usr/local/src/nginx-1.20.2

4.1.4 编译安装

依次执行下面的命令

./configuremakemake install

执行过程

4.1.5 启动nginx

切换到nginx的安装目录

cd /usr/local/nginx

执行下面的命令,启动nginx服务

./sbin/nginx

4.1.6 检查nginx服务是否启动成功

ps -ef | grep nginx

4.1.7 访问nginx主页

如果能够正常启动,访问下80端口,看到下面的效果说明nginx服务启动成功

4.1.8 nginx其他命令补充

这里补充一下其他的几个nginx常用命令

nginx -s reload            # 重新载入配置文件
nginx -s reopen            # 重启 Nginx
nginx -s stop              # 停止 Nginx

4.2 启动另外两个微服务容器

参照2.3 的方式,再启动另外两个服务镜像,使用不同的端口进行区分

docker run -d -it -p 8082:8081 --name=boot-docker-2 boot-docker:1.0
docker run -d -it -p 8083:8081 --name=boot-docker-3 boot-docker:1.0

通过docker ps命令,可以看到三个镜像服务都正常启动了

依次访问一下各自的服务接口,确保可以正常使用

第一个服务

第二个服务

第三个服务

4.3 配置负载均衡

上面的服务环境和nginx服务启动之后,接下来就可以配置负载均衡了

4.3.1 配置nginx负载均衡

将下面的配置信息拷贝到nginx.conf文件中

upstream backend {server 101.221.34.177:8081;server 101.221.34.177:8082;server 101.221.34.177:8083;}server {listen 80;location / {proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}}

配置完成之后,注意重启nginx

4.3.2 负载均衡效果验证

在上面的配置中,配置监听80端口,然后直接被路由到各个服务模块,各个服务模块直接访问自身的默认的那个接口,我们可以通过查看日志观察效果,上述负载均衡的配置中,没有指定具体的方式,默认采用轮询的策略

第一次访问:

第二次访问:

第三次访问:

4.4 固定微服务容器IP的方式配置负载均衡

在上述的操作中,采用的方式是基于同一个原始镜像,启动多个容器的方式,最后配置负载均衡的效果,在目前金仓的部署方式中,各个微服务容器采用的是固定IP的形式启动的,下面再补充一下这种方式的配置过程。

4.4.1 创建一个docker网络

使用下面的命令自定义一个docker网络

  • 指定的IP段根据服务器自身的情况设置

docker network create --subnet=192.168.100.0/24 my_custom_network

4.4.2 使用指定IP的方式启动三个微服务容器

依次执行下面的命令

docker run -d -it -p 8085:8081 --name boot-docker-5 --network my_custom_network --ip 192.168.100.10 boot-docker:1.0
docker run -d -it -p 8086:8081 --name boot-docker-6 --network my_custom_network --ip 192.168.100.11 boot-docker:1.0
docker run -d -it -p 8087:8081 --name boot-docker-7 --network my_custom_network --ip 192.168.100.12 boot-docker:1.0

4.4.3 测试访问服务接口

访问工程中预留的接口,看到如下效果,说明服务正常启动可用了

4.4.4 配置nginx负载均衡

只需要修改一下upstream中的信息即可

 upstream backend {server 192.168.100.10:8085;server 192.168.100.11:8086;server 192.168.100.12:8087;}server {listen 80;location / {proxy_pass http://backend;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}}

4.5 使用Docker Compose配置负载均衡

4.5.1 创建docker网络

使用自定义的网络,可以确保微服务和nginx的容器在同一个网络域

docker network create --driver bridge --subnet=172.19.0.0/24 network1

4.5.2 创建nginx.conf配置文件

自定义一个nginx.conf配置文件,用于在启动nginx容器的时候作映射,可以直接拷贝上面的做简单的修改使用,关键是负载均衡那里的配置

upstream backend {server 172.19.0.5:8085;server 172.19.0.6:8086;}server {listen 80;location / {proxy_pass http://backend;#proxy_pass http://192.168.100.10:8085;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}}

4.5.3 创建docker-compose文件

在nginx.conf相同的目录下创建一个docker-compose文件

参考下面的配置信息,将其拷贝到docker-compose.yml文件中

version: '3'
services:app1:image: boot-docker:1.0container_name: boot-docker-5networks:network1:ipv4_address: 172.19.0.5ports:- "8085:8081"app2:image: boot-docker:1.0container_name: boot-docker-6networks:network1:ipv4_address: 172.19.0.6ports:- "8086:8081"nginx:image: nginx:alpinevolumes:- ./nginx.conf:/etc/nginx/nginx.confports:- "80:80"depends_on:- app1- app2networks:network1:ipv4_address: 172.19.0.7networks:network1:external: true

4.5.4 启动容器

执行下面的命令启动微服务容器,和nginx

docker-compose up -d

验证下是否启动成功

五、写在文末

本文通过实际操作详细演示了如何基于springboot制作微服务镜像,以及开启多个微服务容器配置nginx负载均衡的过程,希望对看到的同学有用哦,本篇到此结束,感谢观看。

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

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

相关文章

1.2.2.1.4 数据安全发展技术发展历程:高级公钥加密方案——同态加密

引言 在密码学领域,有一种技术被图灵奖得主、著名密码学家Oded Goldreich誉为"密码学圣杯",那就是全同态加密(Fully Homomorphic Encryption)。今天我们就来聊聊这个神秘而强大的加密方案是如何从1978年的概念提出&…

vllm量化03—INT4 W4A16

本系列基于Qwen2.5-7B,学习如何使用vllm量化,并使用benchmark_serving.py、lm_eval 测试模型性能和评估模型准确度。 测试环境为: OS: centos 7 GPU: nvidia l40 driver: 550.54.15 CUDA: 12.3本文是该系列第3篇——INT4 W4A16 一、量化 f…

第二十五天打卡

常见报错类型 try-except-else-finally 语句 首先执行try语句,若正确直接执行else语句 若try语句发生错误,则判断错误类型,执行错误类型对应的except语句,不执行else语句 finally语句无条件执行,多用于资源保存&…

城市扫街人文街头纪实胶片电影感Lr调色预设,DNG/手机适配滤镜!

调色详情 城市扫街人文街头纪实胶片电影感 Lr 调色是通过 Lightroom(Lr)软件,对城市街头抓拍的人文纪实照片进行后期调色处理。旨在赋予照片如同胶片拍摄的质感以及电影般浓厚的叙事氛围,不放过每一个日常又珍贵的瞬间&#xff0c…

【hadoop】Kafka 安装部署

一、Kafka安装与配置 步骤: 1、使用XFTP将Kafka安装包kafka_2.12-2.8.1.tgz发送到master机器的主目录。 2、解压安装包: tar -zxvf ~/kafka_2.12-2.8.1.tgz 3、修改文件夹的名字,将其改为kafka,或者创建软连接也可&#xff1…

UDP 多点通信

一、setsockopt/getsockopt 函数详解 1. 函数原型 c #include <sys/socket.h> int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen); int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);…

说一说Node.js高性能开发中的I/O操作

众所周知&#xff0c;在软件开发的领域中&#xff0c;输入输出&#xff08;I/O&#xff09;操作是程序与外部世界交互的重要环节&#xff0c;比如从文件读取数据、向网络发送请求等。这段时间&#xff0c;也指导项目中一些项目的开发工作&#xff0c;发现在Node.js运用中&#…

Charles抓包并破解ProtoBuf请求

安装Charles并抓包 如果是外网的需要root安装一系列证书等&#xff0c;详细见参考文章&#xff1a; 在雷电模拟器安卓7.0上使用Charles抓包详细教程 遇到如下问题&#xff1a; 1.粘贴到目录/system/etc/security/cacerts内&#xff0c;粘贴不了。需要打开这个 2.模拟器wifi打…

Odoo 18 安全组与访问权限管理指南

Odoo 18 安全组与访问权限管理指南 一、准备工作&#xff1a;在自定义模块中创建安全配置文件 创建 security 文件夹 在自定义模块内创建名为 security 的文件夹&#xff0c;用于存放安全组和访问权限的定义文件。 二、定义模型访问权限&#xff1a;ir.model.access.csv 文…

使用lldb查看Rust不同类型的结构

目录 前言 正文 标量类型 复合类型——元组 复合类型——数组 函数 &str struct 可变数组vec Iter String Box Rc Arc RefCell Mutex RwLock Channel 总结 前言 笔者发现这个lldb挺好玩的&#xff0c;可以查看不同类型的结构&#xff0c;虽然这好像是C的东…

uniapp使用ui.request 请求流式输出

正文&#xff1a; 在现代Web开发中&#xff0c;实时数据流和长时间运行的请求变得越来越常见&#xff0c;尤其是在处理大量数据或进行实时通信时。在这种情况下&#xff0c;uniapp 提供的 ui.request 请求方法可以帮助我们轻松实现流式输出请求。本文将介绍如何使用 uni.reques…

如何恢复被勒索软件加密的服务器文件(解密与备份策略)

针对勒索软件加密文件的恢复和解密策略&#xff0c;结合当前数据安全最佳实践&#xff0c;整理应对指南如下&#xff1a; 一、文件解密与修复方法 立即隔离设备‌ 断开网络连接并禁用共享功能&#xff0c;防止病毒横向传播 通过文件后缀异常&#xff08;如.locked、.wxx&…

JS,ES,TS三者什么区别

Java Script(JS)、ECMAScript(ES)、TypeScript(TS) 的核心区别与关联的详细解析,结合技术背景、设计目标及应用场景展开说明: 一、核心定义与关系 JavaScript(JS) 定义:一种动态类型、基于原型的脚本语言,由 Netscape 公司于 1995 年首次开发,用于网页交互功能。角…

【MapReduce入门】深度解析MapReduce:定义、核心特点、优缺点及适用场景

目录 1 什么是MapReduce&#xff1f; 2 MapReduce的核心特点 2.1 分布式处理 2.2 容错机制 3 MapReduce的完整工作流程 4 MapReduce的优缺点分析 4.1 优势 4.2 局限性 5 MapReduce典型应用场景 5.1 适用场景 5.2 不适用场景 6 MapReduce与其他技术的对比 7 总结 1…

【Redis】分布式锁的实现

目录 一、本地锁存在的问题 二、redis实现分布式锁原理 三、使用示例 四、锁误删问题 解决思路 获取锁和释放锁代码优化 五、锁释放的原子性问题 解决思路&#xff08;Lua脚本&#xff09; 使用流程 总结 大家好&#xff0c;我是千语。上期给大家讲了使用悲观锁来解决…

Unity3D对象池设计与实现详解

前言 在Unity3D中&#xff0c;对象池&#xff08;Object Pooling&#xff09;是一种优化技术&#xff0c;用于减少频繁实例化和销毁对象带来的性能开销。以下是对象池的详细设计和实现步骤&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&#xff0c;希望大家可以点…

[Spring]-组件的生命周期

组件生命周期 认识组件的声明周期 实验1 通过Bean指定组件的生命周期 package com.guigu.spring.ioc.bean;Data public class User {private String username;private String password;private Car car;Autowiredpublic void setCar(Car car) {System.out.println("自动…

【golang】网络数据包捕获库 gopacket

详解 github.com/google/gopacket/pcap 包 github.com/google/gopacket/pcap 是 Go 语言中一个强大的网络数据包捕获库&#xff0c;它是 gopacket 项目的一部分&#xff0c;提供了对 libpcap&#xff08;Linux/Unix&#xff09;和 WinPcap&#xff08;Windows&#xff09;的 G…

RBTree的模拟实现

1&#xff1a;红黑树的概念 红⿊树是⼀棵⼆叉搜索树&#xff0c;他的每个结点增加⼀个存储位来表⽰结点的颜⾊&#xff0c;可以是红⾊或者⿊⾊。通过对任何⼀条从根到叶⼦的路径上各个结点的颜⾊进⾏约束&#xff0c;红⿊树确保没有⼀条路径会⽐其他路径⻓出2倍&#xff0c;因…

React 第三十九节 React Router 中的 unstable_usePrompt Hook的详细用法及案例

React Router 中的 unstable_usePrompt 是一个用于在用户尝试离开当前页面时触发确认提示的自定义钩子&#xff0c;常用于防止用户误操作导致数据丢失&#xff08;例如未保存的表单&#xff09;。 一、unstable_usePrompt用途 防止意外离开页面&#xff1a;当用户在当前页面有…