
åçïŒã¯ã³ããŒã¬ãŒã³ã Flickr
NGINXã¯çŽ æŽãããã§ãïŒ ãããããªã¯ãšã¹ãã®åŠçé床ãå¶éããããšã«é¢ãã圌ã®ããã¥ã¡ã³ãã¯ããããå€å°å¶éãããŠããããã«æããŸããã ããã§ãNGINXã§ã®ã¬ãŒãå¶éãšãã©ãã£ãã¯ã·ã§ãŒãã³ã°ã«é¢ãããã®ã¬ã€ããæžãããšã«ããŸããã
ç§ãã¡ã¯ããã€ããã§ãïŒ
- NGINXãã£ã¬ã¯ãã£ãã«ã€ããŠèª¬æããŸãã
- NGINXã®åãå
¥ã/æåŠããžãã¯ãåŠçãã
- ããŸããŸãªèšå®ã§ãã©ãã£ãã¯ã®ããŒã¹ãã®åŠçãèŠèŠåããŸãã
ããã«ããã®èšäºã®ãã¹ããå®éšããã³åçŸããããã®GitHubãªããžããªãšDockerã€ã¡ãŒãžãäœæããŸããã å®éã«åŠã¶ããšã¯åžžã«ç°¡åã§ãã
NGINXèŠæ±é床å¶éãã£ã¬ã¯ãã£ã
ãã®èšäºã§ã¯ããã£ã¬ã¯ãã£ãlimit_req_zone
ã limit_req
ã limit_req_status
ããã³limit_req_level
ãå®è£
ããlimit_req
ã«ã€ããŠlimit_req_status
ãlimit_req_level
ã ãããã«ãããæåŠããããªã¯ãšã¹ãã®HTTPãªã¯ãšã¹ãã¹ããŒã¿ã¹ã³ãŒãã®ã¹ããŒã¿ã¹ãå¶åŸ¡ãããããããã®å€±æããã°ã«èšé²ãããã§ããŸãã
ã»ãšãã©ã®å Žåããªã¯ãšã¹ãã®æåŠã®ããžãã¯ã§æ··ä¹±ããŸãã
æåã«ã zone
ãã©ã¡ãŒã¿ãŒãå¿
èŠãšããlimit_req
ãã£ã¬ã¯ãã£ããåŠçããå¿
èŠãzone
ãŸãã ãªãã·ã§ã³ã® burst
ããã³nodelay
ãããnodelay
ã
ããã§ã¯ã次ã®æŠå¿µã䜿çšãããŸãã
zone
ã¯ãããã±ããããã€ãŸãçä¿¡ãªã¯ãšã¹ããèªã¿åãããå
±æã¹ããŒã¹ãå®çŸ©ããŸãã 1ã€ã®ããã±ãããã«åé¡ããããã¹ãŠã®ãªã¯ãšã¹ãã¯ããã®ã³ã³ããã¹ãã§ã«ãŠã³ãããã³åŠçãããŸãã ããã«ãããURLãIPã¢ãã¬ã¹ãªã©ã«åºã¥ããŠå¶éãèšå®ã§ããŸãã
burst
ã¯ãªãã·ã§ã³ã®ãã©ã¡ãŒã¿ãŒã§ãã 確ç«ããããšã確ç«ãããåºæ¬ã¬ãŒãå¶éãè¶
ããŠåŠçã§ãããªã¯ãšã¹ãã®æ°ã決å®ããŸãã burst
ã¯é床ã§ã¯ãªãããªã¯ãšã¹ãæ°ã®çµ¶å¯Ÿå€ã§ããããšãç解ããããšãéèŠã§ãã
nodelay
ã¯ã burst
ãšå
±æããããªãã·ã§ã³ã®ãã©ã¡ãŒã¿ã§ããããŸãã 以äžã«ããªããããå¿
èŠãªã®ããç解ããŸãã
NGINXã¯ããªã¯ãšã¹ããåãå
¥ãããæåŠããããã©ã®ããã«æ±ºå®ããŸããïŒ
ãŸãŒã³ãèšå®ãããšããã®é床ãèšå®ãããŸãã ããšãã°ã 300r/m
ã§ã¯ã1åããã300件ã®ãªã¯ãšã¹ããåãå
¥ãããã 5r/s
ã§ã¯ã1ç§ããã5件ã®ãªã¯ãšã¹ããåãä»ããããŸãã
ãã£ã¬ã¯ãã£ãã®äŸïŒ
limit_req_zone $request_uri zone=zone1:10m rate=300r/m;
limit_req_zone $request_uri zone=zone2:10m rate=5/s;
ããã2ã€ã®ãŸãŒã³ã«ã¯åãå¶éãããããšãç解ããããšãéèŠã§ãã NGINXã¯ã rate
ãã©ã¡ãŒã¿ãŒã䜿çšããŠãé »åºŠãèšç®ããããã«å¿ããŠãæ°ããèŠæ±ãåä¿¡ã§ããééãèšç®ããŸãã ãã®å ŽåãNGINXã¯æŒåºãã±ãããšåŒã°ããã¢ã«ãŽãªãºã ã䜿çšããŸãã
NGINXã®å Žåã 300r/m
ãš5r/s
åãã§ãã0.2ç§ããšã«1ã€ã®ãªã¯ãšã¹ããã¹ãããããŸãã ãã®å ŽåãNGINXã¯ãªã¯ãšã¹ããåä¿¡ã§ããããã«0.2ç§ããšã«ãã©ã°ãèšå®ããŸãã ãã®ãŸãŒã³ã«é©ãããªã¯ãšã¹ããå°çãããšãNGINXã¯ãã©ã°ãã¯ãªã¢ãããªã¯ãšã¹ããåŠçããŸãã 次ã®èŠæ±ãå°çãããã±ããéã®æéãã«ãŠã³ãããã¿ã€ããŒããŸã æ©èœããŠããªãå ŽåãèŠæ±ã¯ã¹ããŒã¿ã¹ã³ãŒã503ã§æåŠãããŸããæéãåãããã©ã°ãåä¿¡ãèš±å¯ããå€ã«æ¢ã«èšå®ãããŠããå Žåãã¢ã¯ã·ã§ã³ã¯å®è¡ãããŸããã
èŠæ±ã®åŠçãšãã©ãã£ãã¯ã®ã·ã§ãŒãã³ã°ã®é床ãå¶éããå¿
èŠããããŸããïŒ
burst
ãã©ã¡ãŒã¿ã«ã€ããŠèª¬æããŸãããã äžèšã§èª¬æãããã©ã°ã1ãã倧ããå€ãåãããšãã§ãããšæ³åããŠãã ããã ãã®å ŽåãNGINXãåäžã®ããŒã¹ãå
ã§ã¹ãããããå¿
èŠããããªã¯ãšã¹ãã®æ倧æ°ãåæ ããŸãã
ããã¯ããã¯ããæŒãããããã±ããã§ã¯ãªãããããŒã«ãŒãã¹ã±ãããïŒããŒã¯ã³ãã±ããïŒã§ãã rate
ãã©ã¡ãŒã¿ãŒã¯ãªã¯ãšã¹ãéã®æéééã決å®ããŸãããtrue / falseããŒã¯ã³ã§ã¯ãªãã 0
1 + burst
ã«ãŠã³ã¿ãŒãåŠçã0
ã ã«ãŠã³ã¿ãŒã¯ãèšç®ãããæéééãçµéãããã³ã«å¢åããïŒã¿ã€ããŒãããªã¬ãŒããïŒã b+1
æ倧å€ã«éããŸãã ç¹°ãè¿ããŸããã burst
ã¯ãªã¯ãšã¹ãã®æ°ã§ãããéä¿¡ã®é床ã§ã¯ãããŸããã
æ°ãããªã¯ãšã¹ããå°çãããšãNGINXã¯ããŒã¯ã³ã®å©çšå¯èœæ§ããã§ãã¯ããŸãïŒcounter> 0ïŒã ããŒã¯ã³ãå©çšã§ããªãå Žåããªã¯ãšã¹ãã¯æåŠãããŸãã ãã以å€ã®å ŽåãèŠæ±ã¯åãå
¥ããããŠåŠçãããããŒã¯ã³ã¯äœ¿ãæãããããšèŠãªãããŸãïŒã«ãŠã³ã¿ãŒã1ã€æžããŸãïŒã
ãŸããæªäœ¿çšã®ããŒã¹ãããŒã¯ã³ãããå ŽåãNGINXã¯èŠæ±ãåãå
¥ããŸãã ãããã圌ã¯ãã€ãããåŠçããŸããïŒ
å¶éã5r / sã«èšå®ããŸããNGINXã¯ãå©çšå¯èœãªããŒã¹ãããŒã¯ã³ãããå Žåãæšæºãè¶
ããèŠæ±ãåãå
¥ããŸãããèšå®é床ã«èããããããã«åŠçã延æããŸãã ã€ãŸãã ãããã®ããŒã¹ãèŠæ±ã¯å°ãé
ããŠåŠçãããã ãã¿ã€ã ã¢ãŠãã«ãªããŸãã
èšãæããã°ãNGINXã¯ãŸãŒã³ã«èšå®ãããå¶éãè¶
ããããšã¯ãããŸããããè¿œå ã®ãªã¯ãšã¹ãããã¥ãŒã«å
¥ããããããããããé
延ãããŠåŠçããŸãã
ç°¡åãªäŸã瀺ããŸã1r/s
å¶éãããã burst
ã3
ãŸãã NGINXãäžåºŠã«5ã€ã®ãªã¯ãšã¹ããåä¿¡ãããšã©ããªããŸããïŒ
- æåã®ãã®ãåãå
¥ããããåŠçãããŸãã
- èš±å¯ãããã®ã¯1 + 3ã ããªã®ã§ã1ã€ã®èŠæ±ã¯ã¹ããŒã¿ã¹ã³ãŒã503ã§çŽã¡ã«æåŠãããŸãã
- æ®ãã®3ã€ã¯1ã€ãã€åŠçãããŸãããããã«ã¯åŠçãããŸããã NGINXã¯ã
1r/s
é床ã§ããããã¹ããããã確ç«ãããå¶éå
ã«çãŸããŸãããŸããã¯ã©ãŒã¿ã䜿çšããæ°ãããªã¯ãšã¹ãããªãããšãåæãšããŠããŸãã ãã¥ãŒã空ã«ãªããšãããŒã¹ãã«ãŠã³ã¿ãŒãåã³å¢å ãå§ããŸãïŒããŒã«ãŒãã¹ã±ããããã£ã±ãã«ãªãå§ããŸãïŒã
NGINXããããã·ãµãŒããŒãšããŠäœ¿çšãããå Žåããã®èåŸã«ãããµãŒãã¹ã¯1r/s
é床ã§ãªã¯ãšã¹ããåä¿¡ãããããã·ãµãŒããŒã«ãã£ãŠå¹³æ»åããããã©ãã£ãã¯ã®ããŒã¹ãã«ã€ããŠã¯äœãç¥ããŸããã
ãããã£ãŠããã©ãã£ãã¯ã·ã§ãŒãã³ã°ãæ§æããé
延ãé©çšããŠèŠæ±ã®ããŒã¹ããå¶åŸ¡ããããŒã¿ãããŒãå¹³æ»åããŸããã
nodelay
nodelay
ã¯ãNGINXã«ã burst
å€ã§æå®ããããŠã£ã³ããŠå
ã®ãã±ãããåãå
¥ããããã«åŠçããå¿
èŠãããããšãéç¥ããŸãïŒéåžžã®èŠæ±ãšåæ§ïŒã
ãã®çµæããã©ãã£ãã¯ã®ããŒã¹ãã¯åŒãç¶ãNGINXã®èåŸã«ãããµãŒãã¹ã«å°éããŸããããããã®ããŒã¹ãã¯burst
ã«å¶éãããŸãã
ãªã¯ãšã¹ãåŠçã®é床å¶éã®èŠèŠå
ç·Žç¿ã¯äœããæãåºãã®ã«å€§ãã«åœ¹ç«ã€ãšä¿¡ããŠããã®ã§ãNGINXãæèŒããå°ããªDockerã€ã¡ãŒãžãäœæããŸããã èŠæ±åŠçã®é床ãå¶éããããã®ããŸããŸãªãªãã·ã§ã³ãå®è£
ãããŠãããªãœãŒã¹ãæ§æãããŠããŸããåºæ¬çãªå¶éã burst
ããã³nodelay
ã䜿çšããé床å¶éburst
ãããŸãã ããããã©ã®ããã«æ©èœããããèŠãŠã¿ãŸãããã
ããªãåçŽãªNGINXæ§æã䜿çšããŸãïŒããã¯Dockerã€ã¡ãŒãžã«ããããŸãããªã³ã¯ã¯èšäºã®æåŸã«ãããŸãïŒã
limit_req_zone $request_uri zone=by_uri:10m rate=30r/m; server { listen 80; location /by-uri/burst0 { limit_req zone=by_uri; try_files $uri /index.html; } location /by-uri/burst5 { limit_req zone=by_uri burst=5; try_files $uri /index.html; } location /by-uri/burst5_nodelay { limit_req zone=by_uri burst=5 nodelay; try_files $uri /index.html; } }
èŠæ±åŠçé床ãå¶éããããã®ããŸããŸãªãªãã·ã§ã³ãåããNGINXãã¹ãæ§æ
ãã¹ãŠã®ãã¹ãã§ããã®æ§æã䜿çšããŠã10åã®äžŠåãªã¯ãšã¹ããåæã«éä¿¡ããŸãã
ãããèŠã€ããŸãããïŒ
- é床å¶éã®ããã«æåŠããããªã¯ãšã¹ãã®æ°ã¯ïŒ
- åä¿¡ãããªã¯ãšã¹ãã®åŠçé床ã¯ã©ã®ãããã§ããïŒ
ãªã¯ãšã¹ããåŠçããããã®é床å¶éã䜿çšããŠããªãœãŒã¹ã«å¯ŸããŠ10åã®äžŠåãªã¯ãšã¹ããäœæ

èŠæ±ã«å¯ŸããåŠçã®é床å¶éããããªãœãŒã¹ãžã®10ã®åæèŠæ±
ãã®æ§æã§ã¯ã1åããã30ã®ãªã¯ãšã¹ããèš±å¯ãããŠããŸãã ãã ãããã®å Žåã10ã®ãã¡9ã¯æåŠãããŸãã åã®ã»ã¯ã·ã§ã³ã泚ææ·±ãèªãã å ŽåãNGINXã®ãã®åäœã¯é©ãããšã§ã¯ãããŸãã30r/m
ã¯ã2ç§ã§1ã€ã®ãªã¯ãšã¹ãã®ã¿ãééããããšãæå³ããŸãã ãã®äŸã§ã¯ã次ã®èŠæ±ã解決ããã¿ã€ããŒãæ©èœããåã«NGINXã«è¡šç€ºãããããã10åã®èŠæ±ãåæã«æ¥ãŠã1ã€ãã¹ããããããæ®ãã®9ã€ãæåŠãããŸãã
顧客/ãšã³ããã€ã³ãã®ãªã¯ãšã¹ãã®å°ããªã¹ãã€ã¯ãçã延ã³ãŸã
ãããïŒ æ¬¡ã«ãåŒæ°burst=5
ãè¿œå ããŸããããã«ãããNGINXã¯ãèŠæ±ã®åŠçã®é床å¶éã䜿çšããŠããŸãŒã³ã®ãã®ãšã³ããã€ã³ããžã®èŠæ±ã®å°ããªããŒã¹ããã¹ãããã§ããŸãã

åŒæ°burst = 5ã®10ã®åæãªãœãŒã¹èŠæ±
ããã§äœãèµ·ãã£ãã®ã§ããïŒ äºæ³ã©ããã burst
ã§ããã«5ã€ã®ãªã¯ãšã¹ããåãå
¥ããããåèšæ°ã«å¯Ÿããåãå
¥ãããããªã¯ãšã¹ãã®æ¯çã1/10ãã6/10ã«æ¹åãããŸããïŒæ®ãã¯æåŠãããŸããïŒã ããã§ãNGINXãããŒã¯ã³ãæŽæ°ããåä¿¡ãããªã¯ãšã¹ããåŠçããæ¹æ³ãæ確ã«èŠãããšãã§ããŸã-çºä¿¡é床ã¯30r/m
å¶éãããŸããããã¯2ç§ããšã«1ã€ã®ãªã¯ãšã¹ãã«çžåœããŸãã
æåã®èŠæ±ã«å¯Ÿããå¿çã¯ã0.2ç§åŸã«è¿ãããŸãã ã¿ã€ããŒã¯2ç§åŸã«èµ·åããä¿çäžã®èŠæ±ã®1ã€ãåŠçãããã¯ã©ã€ã¢ã³ããå¿çãåãåããŸãã åŸåŸ©ã«è²»ããããåèšæéã¯2.02ç§ã§ããã ããã«2ç§åŸãã¿ã€ããŒãåã³èµ·åãã次ã®èŠæ±ãåŠçã§ããããã«ãªããŸããåèšèŠæ±æéã¯4.02ç§ã§æ»ããŸãã ãªã©ãªã©...
ãããã£ãŠã burst
åŒæ°ã䜿çšãããšãNGINXèŠæ±ã¬ãŒãå¶éã·ã¹ãã ãåçŽãªãããå€ãã£ã«ã¿ãŒãããã©ãã£ãã¯ã·ã§ãŒããŒã«å€ããããšãã§ããŸãã
ç§ã®ãµãŒããŒã¯äœåãªè² è·ãåŠçã§ããŸãããã¯ãšãªã®é床å¶éã䜿çšããŠéè² è·ãé²ããããšæããŸã
ãã®å Žåã nodelay
åŒæ°ã圹ç«ã€å ŽåããããŸãã burst=5 nodelay
ãšã³ããã€ã³ãã«åã10åã®ãªã¯ãšã¹ããéä¿¡ããŸãããïŒ

åŒæ°burst = 5 nodelayã®10ã®åæãªãœãŒã¹èŠæ±
burst=5
ã§äºæ³ãããããã«ãã¹ããŒã¿ã¹ã³ãŒãã¯200ãš503ã®åãæ¯çã«ãªããŸãã ãã ããçŸåšãéä¿¡é床ã¯2ç§ããšã«1ã€ã®èŠæ±ã«å¶éãããŠããŸããã ããŒã¹ãããŒã¯ã³ãå©çšå¯èœã§ããéããçä¿¡èŠæ±ã¯ããã«åãå
¥ããããåŠçãããŸãã ããŒã¹ãããŒã¯ã³ã®æ°ãè£å
ãããšããç¹ã§ã¯ãã¿ã€ããŒã®å¿çé床ã¯äŸç¶ãšããŠéèŠã§ãããé
延ã¯åä¿¡ããèŠæ±ã«ã¯é©çšãããŸããã
çºèšã ãã®å Žåã zone
ã¯$request_uri
䜿çšããŸããããã®åŸã®ãã¹ãŠã®ãã¹ãã¯binary_remote_addr
ãªãã·ã§ã³ãšãŸã£ããåãããã«binary_remote_addr
ãé床ã¯ã¯ã©ã€ã¢ã³ãIPã¢ãã¬ã¹ã«ãã£ãŠå¶éãããŸãã ç¹å¥ã«æºåãããDockerã€ã¡ãŒãžã䜿çšããŠããããã®èšå®ãè©Šãæ©äŒããããŸãã
ãŸãšãããš
NGINXãçä¿¡èŠæ±ãåãå
¥ãã rate
ã burst
ããã³nodelay
åºã¥ããŠããããåŠçããæ¹æ³ãèŠèŠåããŠã¿ãŸãããã
è€éã«ãªããªãããã«ããŸãŒã³èšå®ã§å®çŸ©ãããã¿ã€ã ã©ã€ã³ã«çä¿¡èŠæ±ã®æ°ã衚瀺ããŸãïŒæåŠãŸãã¯åãå
¥ããããŠåŠçãããŸãïŒãã¿ã€ããŒæäœå€ã®çããã»ã°ã¡ã³ãã«åå²ãããŸãã æéééã®çµ¶å¯Ÿå€ã¯éèŠã§ã¯ãããŸããã NGINXãåã¹ãããã§åŠçã§ãããªã¯ãšã¹ãã®æ°ã¯éèŠã§ãã
以äžã¯ããªã¯ãšã¹ãã®åŠçé床ãå¶éããããã®ããŸããŸãªèšå®ãä»ããŠé§åãããã©ãã£ãã¯ã§ãã

ãŸãŒã³ã«èšå®ãããçä¿¡èŠæ±ãšèŠæ±åŠçé床ã®å¶é

èŠæ±ã®åãå
¥ããšæåŠïŒããŒã¹ãèšå®ãªãïŒ
ããŒã¹ããªãïŒã€ãŸãã burst=0
ïŒNGINXã¯é床å¶éãšããŠæ©èœããŸãã èŠæ±ã¯ããã«åŠçãããããããã«æåŠãããŸãã
ããšãã°ãèšå®ãããå¶éå
ã®å®¹éãããŒãããããã«ãã©ãã£ãã¯ã®å°ããªããŒã¹ããèš±å¯ããå Žåã䜿çšå¯èœãªããŒã¹ãããŒã¯ã³å
ã§åä¿¡ãããªã¯ãšã¹ãã®åŠçã®é
延ãæå³ããburst
åŒæ°ãè¿œå ã§ããŸãã

èŠæ±ã®åãå
¥ããé
延ãæåŠïŒããŒã¹ãã䜿çšïŒ
æåŠããããªã¯ãšã¹ãã®ç·æ°ãæžå°ããŠããããšãããããŸãã èšå®ãããé床ãè¶
ããèŠæ±ã®ã¿ãæåŠãããããŒã¹ãããŒã¯ã³ãå©çšã§ããªãç¬éã«å°çããŸããã ãããã®èšå®ã«ãããNGINXã¯ãã©ãã£ãã¯ã®å®å
šãªã·ã§ãŒãã³ã°ãå®è¡ããŸãã
æåŸã«ãNGINXã¯ãªã¯ãšã¹ãã®ããŒã¹ãïŒããŒã¹ãïŒã®ãµã€ãºãå¶éããããšã§ãã©ãã£ãã¯ãå¶åŸ¡ããããã«äœ¿çšã§ããŸããããã®å Žåããªã¯ãšã¹ãã®ããŒã¹ãã¯éšåçã«ããã»ããµïŒäžäœãŸãã¯ããŒã«ã«ïŒã«å°éãããããæçµçã«ã¯çºä¿¡é床ãå®å®ããªããªããŸããããããã¯ãŒã¯é
延ïŒãã¡ããããããã®è¿œå ãªã¯ãšã¹ããåŠçã§ããå ŽåïŒïŒ

èŠæ±ã®åãå
¥ããåŠçãããã³æåŠïŒnodelayã§äœ¿çšãããããŒã¹ãïŒ
ã¯ãšãªã®é床å¶éã§éã¶
ããã§ãæŠèª¬ããæŠå¿µã®ç解ããã匷åºã«ããããã«ãã³ãŒãã調ã¹ããªããžããªãã³ããŒããæºåãããDockerã€ã¡ãŒãžãè©Šãããšãã§ããŸãã
https://github.com/sportebois/nginx-rate-limit-sandbox
åç
§ïŒ
- ãªãªãžãã«ïŒ NGINXã®ã¬ãŒãå¶éã®æŠèŠ ã