码迷,mamicode.com
首页 > Windows程序 > 详细

两个简单的API限流实现方案

时间:2018-08-03 16:30:35      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:add   The   return   red   ops   color   vat   exp   ring   

1, Ngnix限流

Nginx在架构中起到请求转发与负载均衡器的作用。外部req首先到Nginx监听的80端口,然后Nginx将req交给到监听8080端口的APP服务器处理。处理结果再经由Nginx返回给调用方。

Nginx限流的配置:(/usr/local/etc/nginx/nginx.conf)

 1 #user  nobody;
 2 worker_processes  1;
 3  
 4 events {
 5     worker_connections  1024;
 6 }
 7  
 8 http {
 9     include       mime.types;
10     default_type  application/octet-stream;
11  
12     sendfile        on;
13     keepalive_timeout  65;
14  
15     # Rate limitation conf
16     limit_req_zone $binary_remote_addr zone=mylimit:1m rate=1r/s;
17     server {
18         listen       80;
19         server_name  localhost;
20  
21         location / {
22             root   html;
23             index  index.html index.htm;
24         }
25  
26         error_page   500 502 503 504  /50x.html;
27         location = /50x.html {
28             root   html;
29         }
30  
31         # rate limitation and redirection to APP 
32         location ~* /(inventories|prices) {
33             limit_req zone=mylimit;
34             proxy_pass http://localhost:8080;
35         }
36     }
37     include servers/*;
38 }

其中, limit_req_zone $binary_remote_addr zone=mylimit:1m rate=1r/s;
将流量限制为 1QPS,如调用方超过该限制则返回 503

重启nginx:  sudo nginx -s reload

 

2, Redis 计数器

原理: 每个req都对redis中生命周期为一个时间单位的计数器(key:callLimit)加1,如果单位时间内的访问次数超过限制,则拒绝所有后来的请求直到下一个单位时间开始。

 1 public Mono<ServerResponse>  req_handle(ServerRequest request) {
 2         if (callLimitCheck()){
 3             return getResp(request){
 4         … business logics to handle the req …
 5             };
 6         } else {
 7             return ServerResponse.ok().body(Mono.just(“Over call limit!”), String.class);
 8         }
 9     }
10  
11     private boolean callLimitCheck() {
12         String callLimit = this.template.opsForValue().get("callLimit");
13         if(callLimit != null && Integer.valueOf(callLimit)>30) {
14             return false;
15         }   
16         DefaultRedisScript<String> script = new DefaultRedisScript<>(
17         "local current current = redis.call(‘incr‘,KEYS[1]) if tonumber(current) == 1 then redis.call(‘expire‘, KEYS[1], 60) end");
18         script.setResultType(String.class);
19         List<String> keys = new ArrayList<>();
20         keys.add("callLimit");
21         this.template.execute(script, keys);
22         return true;
23     }

上面的代码将有效的QPS限制为 0.5/s ( 30/m).

其中为了避免race condition,将 incr 与 expire两个操作写到一个Lua脚本中实现原子性。

"local current current = redis.call(‘incr‘,KEYS[1]) if tonumber(current) == 1 then redis.call(‘expire‘, KEYS[1], 60) end"

 

 

转自:https://blog.csdn.net/qijin2016/article/details/79284553

两个简单的API限流实现方案

标签:add   The   return   red   ops   color   vat   exp   ring   

原文地址:https://www.cnblogs.com/laoxia/p/9414185.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!