正向代理和反向代理
我们经常看到正向代理和反向代理这两个名词,那么什么是正向代理,什么是反向代理呢?这里我举两个通俗的例子帮助理解这两个概念:
正向代理
假如我们要访问一个网站A,但是由于各种原因无法直接访问到,我们可以借助一个可以访问到网站A的第三方的服务器B,通过服务器B访问网站A,我们通过服务器B访问网站A的这个过程就是正向代理。
反向代理
同样举访问网站A的例子,这个网站A是一个大型网站,我们知道大型网站都是有服务器集群的,我们在访问网站A的时候,怎么找到某个具体的服务器呢?这就需要使用反向代理服务器,通过反向代理服务器可以帮助我们找到A网站服务器集群中的某一台服务器,这个过程就是反向代理。
负载均衡
还是以上面的访问网站A为例,我们在访问网站A的时候,反向代理服务器怎么知道把我们的请求转发到集群中的哪一台服务器呢?同时,为了合理的优化资源,不应该将所有的请求都转发到同一台服务器上,需要根据集群中服务器的运行情况,比如通过CPU占用、带宽等因素决定将请求转发到一个较优的服务器。这个合理分配请求资源的过程就叫做负载均衡。
有很多方案可以实现反向代理和负载均衡,如 Nginx、LVS以及通过硬件手段等。
Nginx
对于中小网站,常用 Nginx 实现反向代理和负载均衡。关于 Nginx 本身又是一个庞大的领域了,本人对具体的细节也不明白,毕竟术业有专攻。因此本文只介绍一般前端工程师常用的一些操作和配置,若想深入 Nginx,还需要您再通过其他的资料加以学习。
安装 Nginx
在 Ubuntu 上,可以通过 apt-get
的方式进行安装:
sudo apt-get install nginx
执行安装后,Nginx 的可执行程序被安装到 /usr/sbin
,路径为 /usr/sbin/nginx
,Nginx 的相关配置配置文件在 /etc/nginx
目录中。
注:以上为 Ubuntu 中的文件结果,不同的 Linux 发行版可能会有差异。
Nginx 的几个常用命令
Nginx 有以下几个常用的命令:
// 启动 Nginx
sudo nginx
// 停止 Nginx
sudo nginx -s stop
// 重载 Nginx 配置文件(平滑重启)
sudo nginx -s reload
// 自定义 Nginx 配置文件
nginx -c xxx.conf
准备两台服务器
要配置反向代理和负载均衡,至少需要三台服务器:一台服务器用来做反向代理和负载均衡,另外两台服务器用来让用户访问。由于我是在本地进行的开发,手头上没有服务器和虚拟机,就在本地使用不同的端口来表示不同的服务器了。
使用 Koa2 创建一个简单的服务器,代码如下:
const Koa = require("koa")
const app = new Koa();
const Router = require("koa-router");
const router = new Router();
// 获取命令行参数
const PORT = process.argv.splice(2)[0];
// 监听端口
app.listen(PORT);
router.get("/",async (ctx,next) => {
ctx.body = `<h1>Server at ${PORT}</h1>`
});
app.use(router.routes());
这里的端口是从命令行参数获取的(您也可以使用在代码中监听随机端口,但这样就不好在 Nginx 负载均衡中指定服务器的地址了),我们可以用其来指定多个服务器。
配置 Nginx 负载均衡
对 Nginx 配置负载均衡比较简单,需要对 http
配置项下的 upstream
和 server
进行配置:
http {
...
upstream mynodeapp {
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
...
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://mynodeapp;
}
...
}
...
}
这样,我们就配置了一个简单的负载均衡服务器。
下面我们启动服务器,打开两个命令行窗口,定位到项目文件夹中,分别运行:
node server 8081
node server 8082
然后在浏览器打开 localhost
,可以反复刷新看下效果:
如上所示,我们已经使用 Nginx 配置了一个简单的负载均衡服务器。
ip_hash
如果对于没有用户验证或者其他验证需求的站点,上面的配置已经足够了。但对于有用户验证之类需求的站点而言,上面的配置是有问题的。因为用户每次刷新页面后不保证能够降落到同一台服务器上,如果需要进行验证操作,当认证成功的用户降落到另一台服务器上时,认证就可能失败。
解决方法也很简单:在 upstream
模块下添加 ip_hash
配置即可,这样会保证用户每次刷新都降落在同一台服务器上:
...
# 配置负载均衡
upstream mynodeapp {
ip_hash;
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
...
看下运行效果:
当我们配置了
ip_hash
之后,用户刷新浏览器都会落到同一台服务器上了。
url_hash
ip_hash
是通过用户的 IP 地址来判断落点,对于固定的 IP 地址较好用,但有时候用户使用的是动态 IP,IP 地址可能是在不断变化的,这时候如果再根据 IP 地址来判断落点就不准确了。我们可以使用 url_hash
来处理这种情况,url_hash
的具体配置和 ip_hash
一致,这里不再赘述了。
访问权重配置
我们还可以对服务器进行访问权重的配置,如果我们事先知道哪一台服务器性能较好,我们可以将它的权重设置的大一点。但一般而言,使用默认的配置就好了,具体着陆到哪一台服务器,由 Nginx 去判断。
# 配置负载均衡
upstream mynodeapp {
server 127.0.0.1:8081 weight=5;
server 127.0.0.1:8082;
}
看下效果:
我们将端口为
8081
的服务器的权重配置的稍大些,在负载均衡时,着陆到该服务器的几率也更大了。
总结
本文主要介绍了使用 Nginx 配置反向代理和负载均衡的初步使用,包括:
- 理解正向代理和反向代理
- 理解负载均衡
- 安装 Nginx 和 Nginx 的常用命令
- 如何使用 Nginx 配置简单的负载均衡服务器
-
ip_hash
,url_hash
和weight
的意义
完。