正向代理与Nginx反向代理和负载均衡

守給你的承諾、 提交于 2021-01-06 06:38:51

文章部分内容 | 圈圈的圈 

链接 | juejin.im/post/5c0e6d606fb9a049f66bf246


知乎:新一993

https://zhuanlan.zhihu.com/p/97235795

近期接触到Nginx,然后就学习记录一下。

前言

代理是个啥

既然要聊反向代理, 那首先得知道代理是个啥吧? 嗯.

正向代理

比如, 你买束花, 想要给隔壁工位的测试妹子小丽表白. 但是又怕被人家直面拒绝太没面子. 于是你把鲜花委托给平时和小丽一起的测试小伙伴小红. 让她帮忙把花送给小丽. 这就是一个简单的代理过程, 小红作为代理帮你把花送给了小丽, 当然这种情况在现实中并不推荐使用, 因为难以避免中间商赚差价 😂.

在上面的例子中, 你作为客户端(请求方), 想要向服务方(小丽)发起请求. 但是碍于面子你主动找到了第三方(小红)作为代理向服务方发送请求, 这种情况就是常说的正向代理. 正向代理在互联网中的使用主要是科学上网, 你想访问谷歌但是碍于防火墙你只能通过vpn服务器作为代理才能访问. 这个时候一般也要找值得信赖的vpn厂商, 避免中间商赚差价 😄.

反向代理

关于反向代理的例子, 那就比较多啦. 比如, 孤独的你躺在床上夜不能寐. 于是乎, 拿出手机, 点亮了屏幕, 拨通 10086, 中国移动就会随机分配一个当前处于空闲的客服MM, 你可以和客服MM聊聊天, 问问她家住哪里, 有没有男朋友, 她的微信号, 她的手机号, 星座, 八字.......

在这个例子中, 中国移动就充当了反向代理的角色. 你只需要拨打 10086. 至于会不会分配到 MM 会分配到哪个 MM 在接通之前你都是不知道的. 反向代理在互联网中的使用主要是实现负载均衡. 当你访问某个网站的时候, 反向代理服务器会从当前网站的所有服务器中选择一个空闲的服务器为你响应. 用于均衡每台服务器的负载率.

修改 hosts 完成域名绑定

mac 用户直接执行 vim /private/etc/hosts 在 hosts 文件最后添加一行:

127.0.0.1 a.com

这一句是什么意思呢? 就是告诉我们的电脑访问 a.com 的时候, 无需请求 DNS, 直接指向我们本机.

ps: win 环境下, hosts 文件在 C:\Windows\System32\drivers\etc 文件夹下. 如果没有权限修改, 把 hosts 文件先拷贝到别的位置, 通过编辑器打开并添加最后一行内容以后再剪切到原来的位置替换即可.

验证: 打开命令行窗口执行 ping a.com, 如果访问的 ip 为 127.0.0.1 说明我们的域名绑定就完成啦 ^_^

安装 nginx


要做 NGINX 反向代理, 肯定要安装 nginx, 本文安装步骤示例环境为 mac, win 的小伙伴, 可以百度一下嗷, 这个东西大同小异.


  • 安装 brew 命令, 执行 ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  • 安装 nginx, 执行  brew install nginx
  • 启动 nginx  nginx , 如果报没有权限, 执行  sudo nginx
Linux安装Nginx:
sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm  (RHEL)sudo yum install -y epel-release   (CentOS) #添加Nginx存储库sudo yum update -ysudo yum install nginx -y    #安装Nginxsudo nginx -v   #查看Nginx版本sudo systemctl start nginx  (sudo service nginx start)   #启动sudo systemctl enable nginx     #系统启动开启 sudo systemctl status nginx     #查看状态http://[你的IP地址]

nginx 启动后, 浏览器打开 localhost:8080, 即可验证. 出现以下界面说明安装成功.



nginx 配置初探

配置完 hosts 域名已经能够成功绑定. 现在如果我们访问 a.com 实际上是会访问到我们的自己的电脑辣. 那还不抓紧试一下?
浏览器访问 a.com
这是什么鬼????
为什么会 无法访问此网站 呢? 我们下载安装完 nginx 还没有做任何配置. 接下来, 我们稍微配置一下就 OK:
  • 命令行切换到 nginx 配置目录下 cd /usr/local/etc/nginx/servers
  • 创建并编辑配置文件 vim test.conf ,  在配置文件中粘贴以下内容
  
    
  
  

server {
    # 监听80端口号
    listen 80;

    # 监听访问的域名
    server_name a.com;

    # 根据访问路径配置
    location / {
        # 把请求转发到 https://www.baidu.com
        proxy_pass https://www.baidu.com;
    }
}

  • 保存文件, 并执行nginx -s reload 重启 nginx.


  • 回到浏览器, 打开 a.com 的页签, 强制刷新.

恭喜你已经完成了第一个 nginx 配置.


创建跨域环境


通过一系列的折腾, 我们已经可以通过 nginx 将 a.com  转发到百度. 完成了第一步, 接下来我们创建跨域的 Case 并一步一步通过 nginx 配置实现跨域.
首先, 项目前后端添加 nginx 目录, 用户存放前后端代码. 代码结构如下图所示.
其次编写前后端代码:
前端代码( ./fe/nginx/index.html ):
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>CORS 实现跨域</title>
</head>
<body>
    <h3>CORS 实现跨域</h3>

    <script>
        var xhr = new XMLHttpRequest()
        xhr.open('GET''http://localhost:8888/api/getFriend')
        xhr.setRequestHeader('token''quanquanbunengshuo')
        xhr.withCredentials = true;
        xhr.onreadystatechange = function() {
            if(xhr.readyState === 4 && xhr.status === 200) {
                console.log(xhr.responseText)
                console.log(xhr.getAllResponseHeaders())
            }
        }
        xhr.send()
    </script>
</body>
</html>
编写完前端代码以后, 启动前端 web 容器.  live-server ./fe/nginx
命令行中出现了黄色警告, 通知我们 8080 端口已经被占用, 这又是为什么呢? 大家请思考一哈.
我们重新指定一个端口 live-server ./fe/nginx --port=9999  哈哈, 换一个指令, 依旧是那么顺畅. ^_^
后端代码:
const http = require('http');

const PORT = 8888;


const server = http.createServer((request, response) => {
  console.log(request.headers)
  response.end("{name: 'quanquan', friend: 'guiling'}");
});


server.listen(PORT, () => {
  console.log('服务启动成功, 正在监听: ', PORT);
});
启动后端服务  node ./be/nginx/index.js

完善 nginx 配置

前后 端代码已经准备完成, 这一步我们就来点干货. 完成最后的配置.


  • 首先, 修改 nginx 配置, 把百度地址替换成本地的前端地址
server {
    # 监听80端口号
    listen 80;

    # 监听访问的域名
    server_name a.com;

    # 根据访问路径配置
    location / {
        # 把请求转发到 http://127.0.0.1:9999
        proxy_pass http://127.0.0.1:9999;
    }
}


  • 修改完成 nginx 配置文件以后, 切记执行 nginx -s -reload 重启 nginx.


  • 访问a.com

熟悉的报错又出现了...
  • 修改前端项目中的接口地址: xhr.open('GET', '/api/getFriend')
  • 修改 nginx 配置文件
  
    
  
  
server {
    # 监听80端口号
    listen 80;

    # 监听访问的域名
    server_name a.com;

    # 根据访问路径配置
    location / {
        # 把请求转发到 http://127.0.0.1:9999
        proxy_pass http://127.0.0.1:9999;
    }

    # 监听根目录下的 /api 路径
    location /api/ {
        # 把请求转发到 http://127.0.0.1:8888
        proxy_pass http://127.0.0.1:8888;
    }
}
新加的对于 api 路径的监听的意思就是把关于后端 api 的请求转发到后端项目上(哈哈, 当然这就是为啥好多后端接口都是要有 /api 开头的啦). 重启 nginx 以后, 再次刷新浏览器, 后端返回的结果已经成功的打印到了控制台, 本次跨域访问任务完成.
细心的小伙伴肯定发现了, 控制台还有一个报错. 这个是因为我们的项目中用到了 live-server 这个工具需要 websocket 导致的. 我们可以通过添加以下配置解决.
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
报错消失 😄, 此时完整的 nginx 配置文件为
server {
    # 监听80端口号
    listen 80;

    # 监听访问的域名
    server_name a.com;

    # 根据访问路径配置
    location / {
        # 把请求转发到 http://127.0.0.1:9999
        proxy_pass http://127.0.0.1:9999;

        # 兼容websocket
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }

    # 监听根目录下的 /api 路径
    location /api/ {
        # 把请求转发到 http://127.0.0.1:8888
        proxy_pass http://localhost:8888;
    }
}
前后端代码地址为: 
https://github.com/luoquanquan/cross-domain/commit/f38f56689fdac1526244ecadaa979a52c9c4a7ea

总结

至此, 我们已经通过 nginx 反向代理的方式实现了跨域访问 api, 在系列文章第一篇对于跨域的解释为: 跨域源于同源策略, 是浏览器保证用户安全的行为. 我们使用的 nginx 反向代理实际上是对浏览器的一种 "哄骗", 让它认为自己访问到的是同域的 api. 实际上是在服务端做了个调包, 这个道理就如同你拨打 10086 你就认定了给你分配到的一定是中国移动的客服MM(客服GG也是有可能出现的 😄)而中国移动的客服MM就是一个很安全的聊天对象, 没有必要再进行限制...


接下来再来学习Nginx更多的内容吧:

什么是反向代理与负载均衡

什么是反向代理

当我们有一个服务器集群,并且服务器集群中的每台服务器的内容一样的时候,同样我们要直接从个人电脑访问到服务器集群服务器的时候无法访问,必须通过第三方服务器才能访问集群这个时候,我们通过第三方服务器访问服务器集群的内容,但是我们并不知道是哪一台服务器提供的内容,此种代理方式称为反向代理

什么是负载均衡

公司会建立很多的服务器,这些服务器组成了服务器集群,然后,当用户访问网站的时候,先访问一个中间服务器,再让这个中间服务器在服务器集群中选择一个压力较小的服务器,然后将该访问请求引入选择的服务器所以,用户每次访问,都会保证服务器集群中的每个服务器压力趋于平衡,分担了服务器压力,避免了服务器崩溃的情况一句话:nginx会给你分配服务器压力小的去访问。

Nginx反向代理与负载均衡的实现

用户访问网站的时候首先会访问nginx服务器,然后nginx服务器再从服务器集群中选择压力较小的服务器,将该访问请求引向该服务器

nginx配置

在如下的文件里进行操作配置
sudo vi /etc/nginx/nginx.conf

nginx常用命令

  • 启动nginx
  • nginx
  • 当你敲完nginx这5个键的时候,并没有任何反应,此时你只需访问localhost:8080(默认)即可
  • 关闭nginx
  • 只需nginx -s stop,停止nginx服务
  • 然后再次启动nginx即可
  • 测试nginx
  • nginx -t #如果出现下面ok和successfull就代表正确了,其他的都不对

nginx:the configuration file/usr/local/etc/nginx/nginx.conf syntaxisoknginx:configuration file/usr/local/etc/nginx/nginx.conf testissuccessful


proxy_pass


nginx反向代理主要通过proxy_pass来配置,将你项目的开发机地址填写到proxy_pass后面,正常的格式为proxy_pass URL即可

server {    listen 80;    location / {        proxy_pass http://10.10.10.10:20186;    }}

Upstream模块实现负载均衡

  • ip_hash指令
  • server指令
  • upstream指令及相关变量
上面写的三个指令,我们直接通过代码来一一分析
// 修改nginx.confworker_processes 1;events {   worker_connections 1024;}  http {    upstream firstdemo {      server 39.106.145.33;      server 47.93.6.93;    }  server {  listen 8080;    location / {      proxy_pass http://firstdemo;    }  }}
  • upstream模  #负载均衡就靠它
    语法格式:upstream name {}
    里面写的两个server分别对应着不同的服务器
  • server模块
    实现反向代理
  • listen监听端口号
  • location / {}访问根路径
  • proxy_pass firstdemo,代理到firstdemo里两个服务器上
上面修改了nginx.conf之后,别忘了最重要的一步重启nginx那么再次访问localhost:8080,会看到如下图页面



还有另一个页面



每次刷新都会访问不同的服务器,这样就做到了负载均衡处理不过,更应该做到的是当用户第一次访问到其中一台服务器后,下次再访问的时候就直接访问该台服务器就好了,不用总变化了。那么就发挥了ip_hash的威力了
// 省略...upstream firstdemo {  ip_hash;  server 39.106.145.33;  server 47.93.6.93;}
ip_hash它的作用是如果第一次访问该服务器后就记录,之后再访问都是该服务器了,这样比如第一次访问是33服务器,那之后再访问也会分配为33服务器访问了

工作中的简单使用

在公司开发项目的时候,遇到设计,产品走查环节的时候,不能每次都让他们去配一个host,毕竟这样不友好,走查起来有麻烦。所以更应该给他们直观的感受,既给一个访问地址就可以看到样子下面给大家看一下,我正常在公司时nginx做的反向代理配置,和咱们上面的如出一辙,只是加了一个server_name,用指定的域名去访问即可
server {    listen 80;    server_name  chd.news.so.m.qss.test.so.com ;    auth_basic off;    location / {        proxy_pass    http://10.10.10.10:20186;        proxy_set_header Host $host;        proxy_redirect off;        proxy_set_header X-Real-IP $remote_addr;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        proxy_connect_timeout 60;        proxy_read_timeout 600;        proxy_send_timeout 600;    }}
每次修改完nginx配置后不要忘记重启nginx才能生效,这样只需要访问chd.news.so.m.qss.test.so.com这个地址就可以查看我的开发环境,进行走查了。这就是nginx最大的功能,反向代理我也接触的不是很多,毕竟不是专业运维出身,可比性差了很多。

点击查看:
Grafana+Influxdb(Prometheus)+Jmeter搭建可视化性能测试监控平台

到此基本上学习了一遍Nginx代理相关的内容,下一篇推文更新上述的监控平台,并使用Nginx代理Grafana/ Prometheus/InfluxDB的端口。


文章合集

Selenium | Appium  | Jenkins  |  Jmeter 

软件测试方法汇总 Postman接口参数化 | 测试用例设计

视频教程

Selenium | Appium | Jenkins | Jmeter


AWS与Docker

如何使用AWS EC2+Docker+JMeter构建分布式负载测试基础架构
Docker容器数据持久化和容器网桥连接
Docker删除image和container
Docker与VM虚拟机的区别以及Docker的特点




END



觉得不错,可以点“在看”,或者转发留言


精彩的内容要和朋友分享

本文分享自微信公众号 - 软测小生(ruancexiaosheng)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!