背景: 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”