Docker 部署 Nginx 实现一个极简的 负载均衡
背景: Nginx是异步框架的网页服务器,其常用作反向代理(负载均衡器)。在一般的小项目中, 服务器不多, 如果不考虑使用服务注册与发现, 使用Nginx 可以容易实现负载均衡。 在特此写一个快速入门 Nginx 的技术贴, 使用 Docker 部署 Nginx, 实现一个极简的加权轮询负载均衡。
Docker 中 安装 Nginx
首先需要在docker 中拉取 nginx 镜像,命令行输入:
复制代码
docker pull nginx:latest
使用 latest 标签会拉取最新的稳定版镜像
拉取成功后使用下面这行命令应该可以看到 nginx:latest 的镜像
复制代码
docker images
随后根据镜像创建容器, 命令行输入
css
复制代码
docker run -d --name mynginx -p 30001:80 nginx:latest
这将在后台运行一个 名为 mynginx 的 nginx 容器, 容器外宿主机的 30001 端口映射到容器内部的 80端口。
安装成功后在浏览器输入: http://localhost:30001/,如果看到 Welcome to nginx 的字样说明Nginx 部署成功:

写一个极简的 后端 handler
新建 一个 nginx_demo 目录 命令行输入
go
复制代码
go mod init nginx_demo go mod tidy
然后 在 nginx_demo 目录下新建一个 server.go 文件:
go
复制代码
package main import ( "fmt" "net/http" ) func HelloHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello From XX.XX.XX.XX.")) # 替换成docker 容器的 IP地址 } func main() { http.HandleFunc("/hello", HelloHandler) errChan := make(chan error) go func() { errChan <- http.ListenAndServe(":20001", nil) }() err := <-errChan if err != nil { fmt.Println("Hello server stop running.") } }
特别注意的是第九行, 需要替换成docker 容器的IP地址, 因为等一会我们需要将这个 go 工程部署到不同的机器上去(docker 容器中), 为了展现效果, 这里直接把IP地址打印出来。
部署 Nginx 和 Go 工程到 docker 中
部署 go 工程
首先我把 这个 go 工程部署到两给不同的 go 容器中去
如何 docker 中搭建 go 开发环境可以参考我的另一篇 文章: 保姆级从0到1讲解go远程开发环境搭建(从Docker安装到使用Goland远程部署和调试)
部署的方式如下表所示:
| IP | 端口映射 (宿主机 -> docker 容器) | http 监听端口 |
|---|---|---|
| 127.17.0.4 | 3333 -> 22 | 20001 |
| 127.17.0.3 | 4444 -> 22 | 20001 |
想要查看 容器 IP 可以输入下面这条命令
scss
复制代码
docker inspect 容器ID(或者容器名)
查看 IPAddress 字段就是 容器 IP
部署 Nginx
更改配置文件
刚才上面已经启动了 Nginx , 我们需要改的只是配置文件
使用 docker cp 命令将 容器内默认的配置文件 复制出来
bash
复制代码
docker cp mynginx:/etc/nginx/nginx.conf nginx.conf
复制出来的配置文件大概长这样:
conf
复制代码
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; include /etc/nginx/conf.d/*.conf; }
我们修改后长这样:
ini
复制代码
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; (必须把这下面行注释掉, 否则会去拉取默认的配置, 导致这个文件的修改不生效) #include /etc/nginx/conf.d/*.conf; upstream RoundWeightLoadBalancer { # 加权 轮询 负载均衡 server 172.17.0.4:20001 weight=1; server 172.17.0.3:20001 weight=2; } server { listen 80; server_name localhost; location / { proxy_pass http://RoundWeightLoadBalancer ; } } }
主要修改了下面几个地方:
1. 注释了 include /etc/nginx/conf.d/*.conf;
这是一个大坑, 如果不注释, 则会去拉取默认的配置, 导致这个文件的修改不生效。我曾就是在这里被坑了一个星期,最后才发现原来是这里出错。
2. 新建了 upStream 标签
upstream 标签后面跟 负载均衡器 的名字, 可以自定义。标签内加 server + IP + 端口。我这里在后面还加了 weight 表示权重。我这里演示的是最简单的轮询加权, 也就是请求一个个按顺序被分配到不同的机器上, 其中 172.17.0.4 机器会被访问到1次, 172.17.0.3 会被访问到两次(因为权重比是1比2). 当然还有别的负载均衡方式, 可以访问 Nginx 的官方文档, 我这里主要关注与快速上手Nginx, 所以就选了给最简单最容易看出效果的 加权轮询策略。
3. 新增了 server 标签
server 标签 主要定义了三件事
- 监听端口
- server name,因为是部署到本地, 直接使用localhost
- location 定义了转发规则, 比如 / 表示将所有请求直接进行转发, 转发到 upstream 标签定义的 RoundWeightLoadBalancer 负载均衡规则
有个很坑的地方: 如果 后端的handler 不位于 docker 容器内, 而是在宿主机, 这就涉及到了了 Nginx 容器如何往外通信的问题. 可以这么写 proxy_pass:
bash
复制代码
proxy_pass http://host.docker.internal:20001/hellou;
使用 host.docker.internal将Nginx的请求转发回宿主机。
重启 Nginx
首先将保存好的 配置文件 复制到 docker 容器中
bash
复制代码
docker cp nginx.conf mynginx:/etc/nginx/nginx.conf
随后重启 Nginx
复制代码
nginx -s reload
运行 起来
在 两个 go 工程的目录下(容器中) 命令行输入
go
复制代码
go mod tidy go run server.go
宿主机 中打开 Postman 或者 浏览器输入 :http://localhost:30001/hello


来自于 Hello From 127.17.0.3 和 Hello From 127.17.0.4 的响应会交替出现, 其中Hello From 127.17.0.3的 响应会连续出现两次, Hello From 127.17.0.4的响应只会出现一次, 这和 1比2 的轮询权重是相符合的。
回顾一下转发过程
宿主机的 30001 端口的请求打到 Nginx 容器的 80端口, Nginx 监听 80端口, 将 / 对应的所有请求转发到 127.17.0.3:20001 和 127.17.0.4:20001, 转发比例为1比2.
下面是配套资料,对于做【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!

软件测试面试小程序
被百万人刷爆的软件测试题库!!!谁用谁知道!!!全网最全面试刷题小程序,手机就可以刷题,地铁上公交上,卷起来!
涵盖以下这些面试题板块:
1、软件测试基础理论 ,2、web,app,接口功能测试 ,3、网络 ,4、数据库 ,5、linux 6、web,app,接口自动化 ,7、性能测试 ,8、编程基础,9、hr面试题 10、开放性测试题,11、安全测试,12、计算机基础

编辑资料获取方式 :xiaobei_upup,添加时备注“csdn alex”


相关文章:
Docker 部署 Nginx 实现一个极简的 负载均衡
背景: Nginx是异步框架的网页服务器,其常用作反向代理(负载均衡器)。在一般的小项目中, 服务器不多, 如果不考虑使用服务注册与发现, 使用Nginx 可以容易实现负载均衡。 在特此写一个快速入门 Nginx 的技术贴, 使用 Docker 部署 Nginx, 实现一个极简的加权轮询负载均…...
Java刷题总结(面试)
1、String类 String不可变 java 中String是 immutable的,也就是不可变,一旦初始化,其引用指向的内容是不可变的。 也就是说,String str “aa”;str“bb”;第二句不是改变“aa”所存储地址的内容…...
ipad air6电容笔推荐,2024十大高性价比电容笔排行榜!
电容笔作为ipad的最佳拍档,为学生党和打工人带来了极大的便利,二者搭配效率真的大大提升,但是,如何选购一支适合自己的电容笔呢?作为一个对数码设备非常感兴趣并且有一定了解的人,我根据自己多年的使用经…...
Java Memorandum
Java Memorandum 1 定义安全的集合2 collection集合用迭代器删除元素时避免并发修改异常3 异常捕获4 RequestBody和RequestParam和Parameter区别4.1 RequestBody4.2 RequestParam4.3 Parameter 1 定义安全的集合 void old() {ArrayList<Apple> apples new ArrayList<…...
大数据学习之 Hadoop部署
Hadoop部署 Linux桌面模式关闭 # 设置 systemctl set-default multi-user.target # 重启 reboot防火墙关闭 systemctl status firewalld systemctl stop firewalld # 关闭开机自启 systemctl disable firewalld配置Java环境 echo $JAVA_HOME java -version # Java配置 # 上传ja…...
xxe漏洞--xml外部实体注入漏洞
1.xxe漏洞介绍 XXE(XML External Entity Injection)是一种攻击技术,它允许攻击者注入恶意的外部实体到XML文档中。如果应用程序处理XML输入时未正确配置,攻击者可以利用这个漏洞访问受影响系统上的敏感文件、执行远程代码、探测内…...
Nginx反向代理与负载均衡:让网站像海豚一样灵活
引言:"当网站遇上海豚:Nginx让数据流动更流畅!"想象一下,你的网站是一片繁忙的海域,而Nginx就像一群聪明的海豚,它们不仅能够迅速地找到最佳的捕食路线(反向代理)…...
企业应考虑的优秀云安全措施
作为云客户,企业有责任确保正确使用他们提供的工具来保证数据和应用程序的安全。让德迅云安全来跟大家一起研究一些典型企业应该考虑的优秀云安全措施。 在数据安全和隐私方面,企业是否在努力跟上疫情的发展?企业不是一个人。就像多年以前,C…...
如何将老板的游戏机接入阿里云自建K8S跑大模型(下)- 安装nvidia/gpu-operator支持GPU在容器中共享
文章目录 安装nvidia/gpu-operator支持GPU在容器中共享 安装nvidia/gpu-operator支持GPU在容器中共享 安装 nvidia/gpu-operator遇到两个问题: 由于我们都懂的某个原因,导致某些镜像一直现在不成功。 解决办法,准备一个🪜&#…...
代码随想录-Day16
104. 二叉树的最大深度 方法一:深度优先搜索 class Solution {public int maxDepth(TreeNode root) {if (root null) {return 0;} else {int leftHeight maxDepth(root.left);int rightHeight maxDepth(root.right);return Math.max(leftHeight, rightHeight) …...
31.@Anonymous
1►@Anonymous原理 大家应该已经习惯我的教学套路,很多时候都是先使用,然后讲述原理。 上节课我们使用了注解@Anonymous,然后接口就可以直接被访问到了,不用token!不用token!不用token!。 我们一般知道,注解是给程序看的,给机器看的,当然也是给程序员看的。注解如果…...
oracle 表同一列只取最新一条数据写法
select * from (select t.*,row_number() over(partition by 去重列名 order by 排序列名 desc) as rnfrom 表名)where rn1 1.row_number() over(....): 为每条数据分配一个行号,1.2.3....这样的 2.partition by : 以某列作为分组,每个分组行号从1开始…...
C语言游戏实战(12):植物大战僵尸(坤版)
植物大战僵尸 前言: 本游戏使用C语言和easyx图形库编写,通过这个项目我们可以深度的掌握C语言的各种语言特性和高级开发技巧,以及锻炼我们独立的项目开发能力, 在开始编写代码之前,我们需要先了解一下游戏的基本规则…...
提权方式及原理汇总
一、Linux提权 1、SUID提权 SUID(设置用户ID)是赋予文件的一种权限,它会出现在文件拥有者权限的执行位上,具有这种权限的文件会在其执行时,使调用者暂时获得该文件拥有者的权限。 为可执行文件添加suid权限的目的是简…...
【leetcode----二叉树中的最大路径和】
二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。 路径和 是路径中各节点值的总和。 给你一个二叉树的根节点 root ,…...
Rust: 编译过程中链接器 `cc` 没有找到
这个错误信息表明在编译过程中链接器 cc 没有找到。cc 通常是 C 编译器的符号链接,它指向系统上的实际 C 编译器,如 gcc 或 clang。这个错误通常意味着你的系统缺少必要的编译工具链。 要解决这个问题,你需要确保你的系统上安装了 C 编译器。…...
【vue-3】动态属性绑定v-bind
1、文本动态绑定: <input type"text" v-bind:value"web.url"> 简写: <input type"text" :value"web.url"> 2、文字样式动态绑定 <b :class"{textColor:web.fontStatus}">vue学…...
Rust:多线程环境下使用 Mutex<T> 还是 Arc<Mutex<T>> ?
在 Rust 中,Mutex 本身不是线程不安全的;它提供了内部的线程同步机制。然而,如果你想在多线程环境中共享同一个 Mutex,你需要确保这个 Mutex 可以被多个线程访问。为此,你通常需要使用 Arc<Mutex<T>>。Arc…...
关于如何创建一个可配置的 SpringBoot Web 项目的全局异常处理
前情概要 这个问题其实困扰了我一周时间,一周都在 Google 上旅游,我要如何动态的设置 RestControllerAdvice 里面的 basePackages 以及 baseClasses 的值呢?经过一周的时间寻求无果之后打算决定放弃的我终于找到了一些关键的线索。 当然在此…...
docker三种自定义网络(虚拟网络) overlay实现原理
docker提供了三种自定义网络驱动:bridge、overlay、macvlan。 bridge驱动类似默认的bridge网络模式。 overlay和macvlan是用于创建跨主机网络。 支持自定义网段、网关,docker network create --subnet 172.77.0.0/24 --gateway 172.77.0.1 my_n…...
西门子PLC通信必备:手把手教你用SCL编写Modbus RTU CRC校验功能块
西门子PLC通信实战:SCL实现Modbus RTU CRC校验的工程化解决方案 在工业自动化领域,可靠的数据通信如同设备的神经系统。当两台PLC需要通过RS485接口交换温度传感器读数时,Modbus RTU协议因其简洁高效成为首选。但许多工程师在调试阶段都会遇到…...
构建本地化个人助理系统:事件驱动架构与模块化设计实践
1. 项目概述:一个高度可定制的个人助理系统最近在GitHub上看到一个挺有意思的项目,叫“Personal-Assistant”,作者是idk-man69。光看名字,你可能会觉得这又是一个类似Siri或Google Assistant的语音助手,但点进去仔细研…...
STM32CubeIDE实战指南:从代码编译到一键下载的完整流程解析
1. STM32CubeIDE开发环境概述 对于刚接触STM32开发的工程师来说,选择一款合适的集成开发环境(IDE)至关重要。STM32CubeIDE是ST官方推出的免费开发工具,它集成了代码编辑、编译、调试和下载功能于一体,特别适合新手快速上手。我在实际项目中使…...
如何快速提升游戏帧率:OpenSpeedy游戏加速优化终极指南
如何快速提升游戏帧率:OpenSpeedy游戏加速优化终极指南 【免费下载链接】OpenSpeedy 🎮 An open-source game speed modifier. 项目地址: https://gitcode.com/gh_mirrors/op/OpenSpeedy 你是否厌倦了游戏卡顿和掉帧?OpenSpeedy是一款…...
VS Code光标主题定制指南:提升开发效率与视觉舒适度
1. 项目概述:一个为开发者量身定制的光标主题集合如果你和我一样,每天有超过8个小时的时间是在代码编辑器里度过的,那么你一定对那个在屏幕上闪烁的光标再熟悉不过了。它不仅仅是文本插入点,更是我们思维在数字世界中的延伸。然而…...
飞书自动化脚本开发指南:从API集成到智能审批机器人实战
1. 项目概述:飞书自动化,从“手动”到“自动”的效能革命 如果你每天的工作,有超过30%的时间是在飞书里重复点击、复制粘贴、手动发送消息和整理表格,那么“cicbyte/feishu-atuo”这个项目,很可能就是你一直在寻找的“…...
天学网口碑好不好?2026年最新用户实测反馈给你答案
作为深耕教育数字化落地领域5年的从业者,最近后台收到不少公立校电教组老师、学生家长的提问:主打AI英语教学的天学网口碑到底怎么样?刚好我们团队刚做完2026年第一季度的英语教育数字化工具落地效果调研,结合一手实测数据给大家客…...
基于Claude API构建可编程AI智能体:从对话到自动化生产单元
1. 项目概述:从Claude中“招聘”一个AI伙伴最近在GitHub上看到一个挺有意思的项目,叫“hire-from-claude”。初看这个标题,你可能会有点摸不着头脑:Claude不是Anthropic公司开发的那个AI助手吗?怎么还能从它那里“招聘…...
MacOS光标增强工具:命令行驱动,实现自动化与个性化配置
1. 项目概述:当光标成为生产力工具如果你是一名长期在macOS上工作的开发者、设计师或者文字工作者,你肯定对系统自带的光标功能又爱又恨。爱的是它简洁流畅,恨的是它在某些高强度、多任务场景下显得力不从心。比如,当你需要在多个…...
[具身智能-767]:AMCL全局撒粒子重搜与局部小范围匹配,是否算法过程是相似的,不同的是:粒子的数量、覆盖的区域、最终的精度?
AMCL 全局重搜 VS 局部匹配 详细对比核心定论二者底层算法流程、运算逻辑、执行步骤 100% 完全一致,统一遵循:运动预测→观测权重计算→粒子重采样→位姿融合输出这套粒子滤波逻辑,仅在粒子分布范围、粒子总数、收敛活动区间、定位误差精度四…...
