Nginx负载均衡
目录
正向代理和反向代理 #
正向代理 #
正向代理服务器是一个位于客户端和原始服务器(origin server)之间的服务器,为了从原始服务器取得内容,客户端向代理发送一个请求并指定目标(原始服务器),然后代理向原始服务器转交请求并将获得的内容返回给客户端。正向代理的典型用途是为在防火墙内的局域网客户端提供访问Internet的途径。 正向代理一般是在客户端设置代理服务器,通过代理服务器转发请求,最终访问到目标服务器。
反向代理 #
反向代理服务器位于用户与目标服务器之间,但是对于用户而言,反向代理服务器就相当于目标服务器,即用户直接访问反向代理服务器就可以获得目标服务器的资源,反向代理服务器负责将请求转发给目标服务器。用户不需要知道目标服务器的地址,也无须在用户端作任何设定,对于用户来说,访问反向代理服务器是完全无感知的。
负载均衡 #
概念 #
早期的网站流量和业务功能都比较简单,单台服务器就可以满足基本需求,但是随着互联网的发展,业务流量越来越大并且业务逻辑也越来越复杂,单台服务器的性能及单点故障问题就凸显出来了,因此需要多台服务器组成应用集群,进行性能的水平扩展以及避免单点故障出现。 应用集群:将同一应用部署到多台机器上,组成应用集群,接收负载均衡器分发的请求,进行业务处理并返回响应数据。 负载均衡器:将用户请求根据对应的负载均衡算法分发到应用集群中的一台服务器进行处理。
此处的负载均衡器,我们将会使用Nginx来实现,而Nginx的负载均衡是基于反向代理的,只不过此时所代理的服务器不是一台,而是多台。
策略 #
除了默认的轮询策略以外,在Nginx中还提供了其他的负载均衡策略,如下
名称 | 说明 | 特点 |
---|---|---|
轮询 | 默认方式 | |
weight | 权重方式 | 根据权重分发请求,权重大的分配到请求的概率大 |
ip_hash | 依据ip分 配方式 | 根据客户端请求的IP地址计算hash值, 根据hash值来分发请求, 同 一个IP发起的请求, 会发转发到同一个服务器上 |
least_conn | 依据最少 连接方式 | 哪个服务器当前处理的连接少, 请求优先转发到这台服务器 |
url_hash | 依据url 分配方式 | 根据客户端请求url的hash值,来分发请求, 同一个url请求, 会发转发 到同一个服务器上 |
fair | 依据响应 时间方式 | 优先把请求分发给处理请求时间短的服务器 |
权重的配置:
#upstream指令可以定义一组服务器
upstream targetserver{
#使用Ip_hash策略
ip hash;
server 192.168.200.201:8080 weight=10;
server 192.168.200.201:8081 weight=5;
}
上述配置的weight权重是相对的,在上述的配置中,效果就是,在大数据量的请求下,最终8080接收的请求数是8081的两倍。
配置负载均衡 #
Docker环境下载镜像 #
docker pull nginx
创建目录 #
mkdir /usr/local/nginx/conf -d
mkdir /usr/local/nginx/www -d
mkdir /usr/local/nginx/logs -d
书写配置文件 #
在/usr/local/nginx/conf
路径下创建 default.conf
:
# upstream是自己写的,一定要放在server外面,切记端口号是自己的
#配置转发到的服务器时, 如果使用容器网路,可以直接使用容器名代替IP地址
upstream myservers {
server 192.168.0.1:8081;
server 192.168.0.2:8082;
}
# server其实默认已经有一个,只需要修改location中配置,指定转发代理即可
server {
location / {
proxy_pass http://myservers;
}
}
运行容器挂载目录 #
这里使用 --net
连接到了一个自定义网络当中,如果没有需要创建。
docker run -itd \
--name nginx --net project \
-v /usr/local/nginx/conf:/etc/nginx/conf.d \
-v /usr/local/nginx/www:/usr/share/nginx/html -v /usr/local/nginx/logs:/var/log/nginx \
-p 80:80 nginx
常用命令 #
# 修改配置文件后,不重启生效
# 测试配置文件修改后的语法是否正确(如果有问题会报错)
nginx -t
# reload命令会重新加载配置文件,nginx服务不会中断
nginx -s reload
# 如果找不到nginx命令的话,需要跳到 /usr/sbin 目录运行
cd /nginx/sbin && ./nginx -t
cd /nginx/sbin && ./nginx -s reload
WebSocket失效的解决方法 #
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/yourdomain.log;
location / {
proxy_pass http://websocket;
proxy_read_timeout 300s;
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
最重要的就是在反向代理的配置中增加了如下两行,其它的部分和普通的HTTP反向代理没有任何差别。
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
这里面的关键部分在于HTTP的请求中多了如下头部:
Upgrade: websocket
Connection: Upgrade
告诉客户端已成功切换协议,升级为Websocket协议。握手成功之后,服务器端和客户端便角色对等,就像普通的Socket一样,能够双向通信。不再进行HTTP的交互,而是开始WebSocket的数据帧协议实现数据交换。
这里使用map指令可以将变量组合成为新的变量,会根据客户端传来的连接中是否带有Upgrade头来决定是否给源站传递Connection头,这样做的方法比直接全部传递upgrade更加优雅。
默认情况下,连接将会在无数据传输60秒后关闭,proxy_read_timeout参数可以延长这个时间或者源站通过定期发送ping帧以保持连接并确认连接是否还在使用。
nginx启动或者重启提示信息如下:
nginx: [emerg] unknown “connection_upgrade” variable nginx: configuration file /www/server/nginx/conf/nginx.conf test failed
解决方法 在nginx配置文件http标签下添加如下几行:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}