# Chap3 流量管理

# 简介

  • Nginx作为一个流量管理器,能百分比分割用户请求,使用用户的地理信息,并控制流量的速度,连接数,限制带宽,这些特征能混合起来创造无数可能

# A/B Testing

  • 需要将用户分割到两个或多个的文件或者应用去完成在线测试
  • 在电商网站的前端A/B测试,验证市场
  • 此功能可以实现应用的灰度发布,减少错误的影响范围
split_clients "${remote_addr}AAA" $variant {
  20.0% "backendv2";
  *			"backendv1";
}
location / {
  proxy_pass http://$variant
}
  • 根据用户的IP地址来哈希,将20%的用户分到第二版的后端,剩下的用户分到第一版的后端
  • 其中,backendv1和backendv2代表两个上游服务器集群,再按照上一篇讲的分别配置两个集群即可

# GeoIP 模块和数据库

  • 用于记录和校验用户连接的位置,关于数据库更新升级的问题,参见这里 (opens new window)
  • 此模块能提供以下变量
    • geoip_country_code:两个字母的国家编码,如CN,US
    • geoip_country_code3:三个字母的国家编码,如CHN,USA
    • geoip_country_name :国家全称,如'China', 'United States'
    • geoip_city_country_code
    • geoip_city_country_code3
    • geoip_city_country_name
    • geoip_city_continent_code
    • geoip_latitude
    • geoip_longtitude
    • geoip_postal_code
    • geoip_region
    • geoip_region_name
    • geoip_area_code:仅在美国有效,返回三位的电话区号
# 安装geoip模块 Debian/Ubuntu or RHEL/CentOS, 商业版的装 nginx-plus-module-geoip
apt-get install nginx-module-geoip  or   yum install nginx-module-geoip
# 安装geoip的国家和城市数据库
mkdir /etc/nginx/geoip
cd /etc/nginx/geoip
wget "http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz"
gunzip GeoIP.dat.gz
wget "http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz"
gunzip GeoLiteCity.dat.gz
# 在Nginx配置文件中添加

load_module "/usr/lib61/nginx/modules/ngx_http_geoip_module.so";

http {
  geoip_country /etc/nginx/geoip/GeoIP.dat;
  geoip_city /etc/nginx/geoip/GeoLiteCity.dat;
  ...
}

# 根据国家限流

  • 这是根据geoip模块的一个字段进行映射限流,可以尝试使用其他字段,达到组合拳的效果
load_module "/usr/lib61/nginx/modules/ngx_http_geoip_module.so";

http {
  map $geoip_country_code $country_access {
    "US" 0;
    "RU" 0; 
    default 1;
  }
}
server {
  if($country_access = '1') {
    return 403; # 仅美国和俄罗斯可以访问
  }
}

# 定位原始用户

load_module "/usr/lib64/nginx/modules/ngx_http_geoip_module.so";
http {
        geoip_country /etc/nginx/geoip/GeoIP.dat;
        geoip_city /etc/nginx/geoip/GeoLiteCity.dat;
  			# 单IP定义或者使用CIDR方式定义可信地址,对于可信地址,nginx通过请求头中的 X-Forwarded-For 来寻找用户IP
        geoip_proxy 10.0.16.0/26;  
        geoip_proxy_recursive on;  # 递归找下去,直到第一个不可信的地址
... 
}

# 限制连接

  • 根据预定义的关键字,如用户IP,来限制连接的数量,一定程度上避免资源滥用
  • limit_conn,limit_conn_status字段在http,server,location的context中有效
  • limit_conn_zone字段只在http的context中有效
http {
	limit_conn_zone $binary_remote_addr zone=limitbyaddr:10m; # 建造了10MB大小的共享内存
  limit_conn_status 429;  # 429代表请求过多,建议用这个取代默认值503,因为503代表服务不可用
  ...
  server {
  	...
    limit_conn limitbyaddr 40;
    ...
  }
}

# 限制速度

  • 根据预定义关键字,如用户IP,限制请求速度,避免DNS攻击
  • 可定义字段limit_req_log_level,默认级别为error,可定义为info,notice,warn,error,记录超速访问的事件
  • 关于burst 和 nodelay 的精确解释 (opens new window)
    • burst=5:burst爆发的意思,这个配置的意思是设置一个大小为5的缓冲区当有大量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内等待,但是这个等待区里的位置只有5个,超过的请求会直接报错返回
    • nodelay:
      • 如果设置,会在瞬时提供处理(burst + rate)个请求的能力,请求超过(burst + rate)的时候就会直接返回503,永远不存在请求需要等待的情况。(这里的rate的单位是:r/s)
      • 如果没有设置,则所有请求会依次等待排队
http {
	limit_req_zone $binary_remote_addr zone=limitbyaddr:10m rate=1r/s;
  limit_req_status 429;
  ...
  server {
  	...
		# burst默认为0,nodelay是可选参数
    limit_req zone=limitbyaddr burst=10 nodelay; 
    ...
  }
}

# 限制带宽

  • 对于你的资源,限制单个用户的下载带宽
  • 以下代码:对于下载download文件夹下的资源,在下载10MB过后,将被限速为1MB/s
location /download/ {
  limit_rate_after 10m; # 默认值为0,无限制
  limit_rate 1m; # 默认值为0,无限制
}
最后更新: 5/31/2022, 6:43:40 AM