1. 背景说明
公司每次一搞活动,总是有大量的羊毛客来撸羊毛,后端的java和数据库真是苦不堪言,而且活动开始的时候,正真的用户很难抢到,用户很质疑活动的真实性,投诉也挺多的,确实挺伤脑筋的,都被一些机器人脚本给抢了,12306买票大家应该都懂了.
2. 解决思路(包含过程)
开发修改逻辑限制一些会员的刷单行(此处省略1万字),当然站在运维的角度肯定也是希望这样去做的,但是站在开发的角度,肯定是不希望变的太复杂,这里就不扯这么多,这个本身是说不清楚的,既然是站在运维的角度,我们就从运维的角度出发去思考如何解决问题吧.
曾经尝试的方法
基于URL来进行限速: 缺点好人坏人不分,虽然能限制但是粒度太粗 不是特别合适
基于源IP地址进行限速: 缺点NAT出口的IP很容易被误杀,因为我们的业务是有很多会用到NAT的,再加上羊毛客只要IP够多,也没办法精准封杀, 所以不适用
基于请求头进行限速: 我们的用户登陆以后肯定会有一个token,而且这个token肯定是唯一的,这样即使这个用户更换IP我们的token不变的情况下,就能精准识别到这是一个异常的用户(当然这并不能涵盖所有场景,比方说你们的token一但用户更换IP就会重新登录)
3. 解决办法
1. nginx的配置
http段新增一个配置:
limit_req_zone $limit zone=one:10m rate=1r/s; #zone是名字,可以自己定义, rate定义的速率1请求/秒
2. 配置MAP
map $http_x_http_token $limit {
default "";
"~.+" $http_x_http_token;
}
3. ingress的配置
先修改ingress的configmap 增加
http-snippet: |
map $http_x_http_token $limit {
default "";
"~.+" $http_x_http_token;
}
limit_req_zone $limit zone=one:20m rate=1r/s;
增加ingress限速规则(创建单独的location) 在annotations:下增加
nginx.ingress.kubernetes.io/configuration-snippet: |
limit_req zone=one nodelay