转载于思否 宜信技术学院 segmentfault.com/a/119000002…
Nginx的负载均衡策略
负载均衡就是将请求“均衡”地分配到多台业务节点服务器上。这里的“均衡”是依据实际场景和业务需要而定的。 对于Nginx来说,请求到达Nginx,Nginx作为反向代理服务器,有绝对的决策权,可以按照规则将请求分配给它知道的节点中的一个,通过这种分配,使得所有节点需要处理的请求量处于相对平均的状态,从而实现负载均衡。 Nginx支持的负载均衡策略很多,比较重点的如下:
- round robin(轮询)
- random(随机)
- weight(权重)
- fair(按响应时长,三方插件)
- url_hash(url的hash值)
- ip_hash(ip的hash值)
- least_conn(最少连接数)
负载均衡策略归类
这么多的策略,非常不利于记忆和选择,我们不妨将这些常见的策略归类,分而化之,方便挑选。
第一类 最佳实现
- weight(权重)
- random(随机) 最佳实践,其实就是最常见、最普通的默认配置,当然也是在一定程度上最好用的配置。不知道用什么方式的时候,就可以选择用这一类型。 轮询不用多说。这里的随机,其实在大量请求的情况下,按照概率的理论等同于轮询的方式。
轮询配置参考:
#默认配置就是轮询策略
upstream server_group {
server backend1.example.com;
server backend2.example.com;
}
随机配置参考:
upstream server_group {
random;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
server backend4.example.com;
}
第二类 性能优先
- weight(权重)
- fair(按响应时长,三方插件)
- least_conn(最少连接数)
让业务节点中性能更强的机器得到更多请求,这也是一个比较好的分配策略。 什么是性能更好的机器?这个问题也有很多的维度去考量。
- 从经验或硬件上分为高权重、低权重的机器。
- 按照节点请求的响应时长来决定是多分配请求,还是少分配请求。
- 按照保持的连接数。一般来说保持的连接数越多说明处理的任务越多,也是最繁忙的,可以将请求分配给其他机器处理。
权重的配置参考:
upstream server_group {
server backend1.example.com weight=5;
#默认为不配置权重为1
server backend2.example.com;
}
响应的时长(fair)配置参考
需要在Nginx编译时加入nginx-upstream-fair模块。
upstream server_group{
fair;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
server backend4.example.com;
}
最少连接数(least_conn)配置参考:
upstream server_group {
least_conn;
server backend1.example.com;
server backend2.example.com;
}
第三类 保持稳定
- ip_hash
- url_hash 很多请求都是有状态的,上一次请求到哪个业务节点,这次还要请求到哪台机器。比如常见的session就是这样一种有状态的业务。 这里Nginx提供了按照客户端ip的hash来作为用户的标示分配、url的hash作为分配标示的规则。本质上还是要找到用户的请求中不变的要素,抽离出来,这样就可以进行分配了。
ip_hash配置参考:
upstream server_group {
ip_hash;
server backend1.example.com;
server backend2.example.com;
}
url_hash配置参考:
upstream server_group{
hash $request_uri consistent;
server backend1.example.com;
server backend2.example.com;
server backend3.example.com;
server backend4.example.com;
}
二、Nginx支持一致性哈希进行分配
Nginx支持一致性hash进行分配,也就是配置中consistent。 什么是一致性hash?为什么要引入这个机制?在生产环境下,业务节点经常会出现增加或减少的情况,就算这种增加或减少都是被动的,也可能会对hash分配产生影响。如何能够做到尽量减少影响呢?这时一致性hash被发明出来。 一致性hash解决两个问题:
- 分配特别不均匀;
- 节点变动除了对分配到这个节点上的请求有影响,还会导致其他节点上的请求重新分配。
1)如何解决分配不均的问题
将原来的每一个节点复制出N个虚拟节点,并且给这些虚拟节点都起个名字。
比如原来有5个节点,分配的时候经常会不均匀,现在每个节点都虚拟出N个节点,
就是5*N个节点,会极大降低分配不均匀的情况。下面就要说说如何分配的问题了。
2)如何解决节点变动的问题
一致性哈希的基本思想:
- 定义一个[0,(2^32)-1]的数值空间。相当于取长度从 0到2^32-1 的线段。
- 节点映射到线段上。将每个节点,包括虚拟节点,都通过hash算法得到数值,然后映射到这个取值区间上。如下图
-
- 计算数据的Hash值。把请求中的关键字符串通过hash算法得到一个数值,在线段中找到一个位置,如果算出来的数值大于2^32-1则认为是0。按照这个规则,其实是把这个线段首尾相连形成一个环,所以也叫hash环。
- 数据节点在线段上找归属的节点。沿着这个线段向右找到离得最近的节点,并把该节点作为这个数据的归属节点。
下面再来看节点的变化对一致性Hash的影响。
- 节点减少:比如NodeA突然故障了,原来分配到其他节点上的数据不会发生变化,只有分配到NodeA上的数据会重新找离它们最近的点,从而减少了hash重新分配的数量。这也是一致性hash最大的优势。
- 节点增加:比如现在请求量抖增,需要增加节点降低负载。当新加入节点NodeE时,NodeE及它的一群虚拟节点会根据hash值分配在hash环上。这时,大部分数据再根据一致性哈希规则找其归属的Node节点都不会发生变化,只有那些值计算出来发现离NodeE更近的数据发生了变化,但数量毕竟是有限的,减少了因为节点增加造成的影响。
三、故障节点摘除与恢复(健康检查)
先看看经典配置,再详细解释。
upstream server_group {
server backend1.example.com ;
server backend2.example.com max_fails=3 fail_timeout=30s;
server backup1.example.com backup;
}
max_fails=number
这个参数决定了多少次请求后端失败后会暂停这个业务节点,不再给它发新的请求,默认值是1。此参数需要配合fail_timeout一起用。
题外话:如何定义失败,有很多种类型,这里因为主要处理HTTP代理,所以更关注proxy_next_upstream。 proxy_next_upstream:主要定义了当服务节点出现状况时,会将请求发给其他节点,也就是定义了怎么算作业务节点失败。
fail_timeout=time
决定了当Nginx认定这个节点不可用时,暂停多久。不配置默认就是10s。 把上面两个参数联合起来考虑就是:当Nginx发现发送到这个节点上的请求失败了3次的时候,就会把这个节点摘除,摘除时间是30s,30s后才会再次发送请求到这个节点上。
backup
类似于switch语句中的default,当主要节点都挂了的时候,会把请求打到这个backup节点。这是最后一个救兵了。
Https 配置
Nginx 常用来配置Https认证,主要有两个步骤:签署第三方可信任的 SSL 证书 和 配置 HTTPS
-
签署第三方可信任的 SSL
配置 HTTPS 要用到私钥 example.key 文件和 example.crt 证书文件,而申请证书文件的时候要用到 example.csr 文件
-
Nginx配置https
要开启 HTTPS 服务,在配置文件信息块(server),必须使用监听命令 listen 的 ssl 参数和定义服务器证书文件和私钥文件,如下所示:
server {
#ssl参数
listen 443 ssl; //监听443端口,因为443端口是https的默认端口。80为http的默认端口
server_name example.com;
#证书文件
ssl_certificate example.com.crt;
#私钥文件
ssl_certificate_key example.com.key;
}
ssl_certificate:证书的绝对路径
ssl_certificate_key: 密钥的绝对路径;
IP白名单
可以配置nginx的白名单,规定有哪些ip可以访问你的服务器,防爬虫必备
简单配置
server {
location / {
deny 192.168.0.1; // 禁止该ip访问
deny all; // 禁止所有
}
}
白名单配置
建立白名单
vim /etc/nginx/white_ip.conf
...
192.168.0.1 1;
...
修改nginx配置(nginx.conf)
geo $remote_addr $ip_whitelist{
default 0;
include ip.conf;
}
// geo 指令主要是可以根据指定变量的值映射出一个新变量。 如果不指定变量,默认为$remote_addr
为匹配项做白名单设置
server {
location / {
if ( $ip_whitelist = 0 ){
return 403; //不在白名单返回 403
}
index index.html;
root /tmp;
}
}
适配PC与移动环境
当用户从移动端打开PC端baidu.com的场景时,将自动跳转指移动端m.baidu.com,本质上是Nginx可以通过内置变量$http_user_agent,获取到请求客户端的userAgent,从而知道当前用户当前终端是移动端还是PC,进而重定向到H5站还是PC站
server {
location / {
//移动、pc设备agent获取
if ($http_user_agent ~* '(Android|webOS|iPhone)') {
set $mobile_request '1';
}
if ($mobile_request = '1') {
rewrite ^.+ http://m.baidu.com;
}
}
}
配置gzip
开启Nginx gzip,压缩后,静态资源的大小会大大的减少,从而可以节约大量的带宽,提高传输效率,带来更好的响应和体验
server{
gzip on; //启动
gzip_buffers 32 4K;
gzip_comp_level 6; //压缩级别,1-10,数字越大压缩的越好
gzip_min_length 100; //不压缩临界值,大于100的才压缩,一般不用改
gzip_types application/javascript text/css text/xml;
gzip_disable "MSIE [1-6]\."; // IE6对Gzip不友好,对Gzip
gzip_vary on;
}
Nginx配置跨域请求
跨域是前端工程师都会面临的场景,跨域的解决方案有很多。不过要知道在生产中,要么使用 CORS 、要么使用 Nginx 反向代理来解决跨域。在 Nginx 的配置文件中进行如下配置即可:
- 使用 Nginx 反向代理
server {
listen 80;
server_name localhost; # 用户访问 localhost,反向代理到 http://webcanteen.com
location / {
proxy_pass http://webcanteen.com
}
}
- 当出现403跨域错误的时候,还有 No 'Access-Control-Allow-Origin' header is present on the requested resource报错等,需要给Nginx服务器配置响应的header参数:
location / {
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
if ($request_method = 'OPTIONS') {
return 204;
}
}
如何使用Nginx
通过在本地使用Nginx,从启动、更改、重启等环节来介绍Nginx的基本使用
- 如何启动
如何启动 sudo nginx
修改 nginx.conf 配置 (具体看你配置位置)
vim /usr/local/etc/nginx/nginx.conf
检查语法是否正常 sudo nginx -t
重启 nginx sudo nginx -s reload
创建软链接(便于管理多应用nginx)
当我们需要管理多个网站的nginx,nginx文件放在一起是最好的管理方式,一般都存在/nginx/conf.d/,我们需要把配置文件丢到 /etc/nginx/conf.d/ 文件夹下,怎样才能使这个配置文件既在程序文件夹下,又在 /etc/nginx/conf.d/文件夹下呢?
假如我们在程序文件夹下有一个 ngxin 配置文件:/home/app/app.nginx.conf 我们需要给这个文件创建一个软链接到 /etc/nginx/conf.d/ 下:
ln -s /home/app/app.example.com.nginx.conf
/etc/nginx/conf.d/app.nginx.conf
这样操作之后,当我们改应用配置文件,/etc/nginx/conf.d/ 下与之对应的配置文件也会被修改,修改后重启 nginx 就能够使新的 ngxin 配置生效了。
作者:树酱 链接:juejin.cn/post/684490… 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。