рдирд┐рд╡реЗрджрди рд╕реАрдорд╛ - рд░реЗрдЯрд▓рд╛рдорд┐рдЯрд░

рдпрджрд┐ рдЖрдк рдбрд░рддреЗ рд╣реИрдВ рдХрд┐ рдЖрдкрдХреА рд╡реЗрдм рд╕реЗрд╡рд╛ рдХреЛ рд▓рд╛рдкрд░рд╡рд╛рд╣ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдУрдВ рджреНрд╡рд╛рд░рд╛ рд░реЛрдХрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ, рдпрд╛ рдЖрдкрдХреЗ рдкрд╛рд╕ рдмрд╕ рдПрдХ рдХрдордЬреЛрд░ рд╕рд░реНрд╡рд░ рд╣реИ, рддреЛ рдЖрдкрдиреЗ рдкрд╣рд▓реЗ рд╣реА рдкреНрд░рддреНрдпреЗрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реЛрдЪрд╛ рд╣реИред рдПрдХ рдЕрдЪреНрдЫреЗ рддрд░реАрдХреЗ рд╕реЗ - рдпрд╣ рдХреЗрд╡рд▓ рдПрдХ рдЖрд╡рд╢реНрдпрдХ рд░рдХреНрд╖рд╛ рдХреНрд╖реЗрддреНрд░ рд╣реИред рдмреЗрд╢рдХ, рдЗрд╕ рддрд░рд╣ рдХреА рд╕реАрдорд╛ рдЧрдВрднреАрд░ рд╣рдорд▓реЗ рд╕реЗ рдирд╣реАрдВ рдмрдЪрд╛рдПрдЧреА, рд▓реЗрдХрд┐рди рдХреАрдордд / рдЧреБрдгрд╡рддреНрддрд╛ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ рдпрд╣ рдХрд╛рдлреА рдЙрдкрдпреБрдХреНрдд рд╣реИ

рд╣рд╛рд▓ рд╣реА рдореЗрдВ, рдореИрдВрдиреЗ рдПрд░реНрд▓рд╛рдВрдЧ рдореЗрдВ рд╕рдХреНрд░рд┐рдп рд░реВрдк рд╕реЗ рдЬреБрдбрд╝рдирд╛ рд╢реБрд░реВ рдХрд┐рдпрд╛ред рдЦреИрд░, рд╣рдореЗрд╢рд╛ рдХреА рддрд░рд╣, рд╕рд╛рдордЧреНрд░реА рдХреЛ рдордЬрдмреВрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВрдиреЗ рдореЛрдЪреАрд╡реЗрдм рдкрд░ рдПрдХ рд╕рд╛рдзрд╛рд░рдг рд╡реЗрдм рд╕реЗрд╡рд╛ рд▓рд╛рдЧреВ рдХреАред рдореЛрдЪреАрд╡реЗрдм рд╡реЗрдм рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдмрд╣реБрдд рд╣реА рд╕рднреНрдп рдврд╛рдВрдЪрд╛ рд╣реИ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдПрдХ рдЧреНрд░рд╛рд╣рдХ рд╕реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдирд╣реАрдВ рдорд┐рд▓реАред рддреЛ рдореИрдВрдиреЗ рдЦреБрдж рдХрд┐рдпрд╛ред

рдХреНрдпреЛрдВрдХрд┐ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд╕реАрдорд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реА рдХреНрд╡реЗрд░реА рдХреА рдЧрддрд┐ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдЕрд▓рдЧ рд╣реИ рдФрд░ рдХрд┐рд╕реА рднреА рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдп рд╕реЗ рдмрдВрдзреА рдирд╣реАрдВ рд╣реИ, рдореИрдВрдиреЗ рдПрдХ рд╕реНрд╡рддрдВрддреНрд░ рдЕрдиреБрдкреНрд░рдпреЛрдЧ рдореЗрдВ рдмрдирд╛рдП рдЧрдП рдореЙрдбреНрдпреВрд▓ рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ рдФрд░ рдЗрд╕рдХреЗ рд╕реНрд░реЛрдд рдХреЛрдб рдХреЛ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред

рдХрд╛рд░реНрдп

рддреЛ, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ Erlang / OTP , Mochiweb, rebar рд╣реИ ред рдореИрдВ рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдкрдврд╝рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдФрд░ рдпрджрд┐ рдЕрдиреБрд░реЛрдз рдмрд╣реБрдд рдмрд╛рд░ рдЬрд╛рддреЗ рд╣реИрдВ рддреЛ рдЙрд╕реЗ 413 рддреНрд░реБрдЯрд┐ рдХреЛрдб рджреЗрддреЗ рд╣реИрдВред рдЧреНрд░рд╛рд╣рдХ рдХреА рдкрд╣рдЪрд╛рди рдЙрд╕рдХреЗ рдЖрдИрдкреА рдкрддреЗ рд╕реЗ рдХреА рдЬрд╛рддреА рд╣реИред рд╡рд╣ рдЬреЛ mochiweb_request:get(peer). рджреЗрддрд╛ рд╣реИ mochiweb_request:get(peer).

рдХрд╛рд░реНрдп рдЗрддрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╢рд╛рдпрдж рдПрдХ рдЯрд░реНрдирдХреА рд╕рдорд╛рдзрд╛рди рдХрд┐рд╕реА рдХреЗ рд╕рдордп рдХреЛ рдмрдЪрд╛рдПрдЧрд╛ред

рджреГрд╖реНрдЯрд┐рдХреЛрдг

рдореИрдВрдиреЗ рдЯреЛрдХрди рдмрд╛рд▓реНрдЯреА рдПрд▓реНрдЧреЛрд░рд┐рдереНрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ред
рдпрджрд┐ рд╣рдо рдЗрд╕рдХрд╛ рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ рд╡рд░реНрдгрди рдХрд░рддреЗ рд╣реИрдВ, рддреЛ рд╣рдо рдкреНрд░рддреНрдпреЗрдХ рдЧреНрд░рд╛рд╣рдХ рдХреЗ рд▓рд┐рдП рдХреБрдЫ рд╕рдордп рдЕрдВрддрд░рд╛рд▓реЛрдВ рдХреЛ рдЯреЛрдХрд░рд┐рдпрд╛рдБ рдорд╛рдирддреЗ рд╣реИрдВ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдЗрд╕ рд╕рдордп рдЕрдВрддрд░рд╛рд▓ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрдиреБрд░реЛрдз рдЬреЛрдбрд╝реЗрдВрдЧреЗред рдЯреЛрдХрд░реА рдореЗрдВ рдПрдХ рд╕реАрдорд┐рдд рдорд╛рддреНрд░рд╛ рд╣реЛрддреА рд╣реИред рдЬреИрд╕реЗ рд╣реА рдЯреЛрдХрд░реА рдХреЛ рд╕реАрдорд╛ рддрдХ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЗ рд╕рд╛рде рднрд░рд╛ рдЬрд╛рддрд╛ рд╣реИ, рд╣рдо рдЧреНрд░рд╛рд╣рдХ рдХреЛ рд╕реЗрд╡рд╛ рджреЗрдирд╛ рдмрдВрдж рдХрд░ рджреЗрддреЗ рд╣реИрдВред рдХреНрдпреЛрдВрдХрд┐ рд╕рдордп рдЖрдЧреЗ рдмрдврд╝рддрд╛ рд╣реИ, рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рд▓рд┐рдП рдмрд╛рд╕реНрдХреЗрдЯ рд▓рдЧрд╛рддрд╛рд░ рдмрджрд▓ рд░рд╣реЗ рд╣реИрдВ, рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рдкрд╛рд╕ рдирдП рд╕рдордп рдЕрдВрддрд░рд╛рд▓ рдкрд░ рд╕реЗрд╡рд╛ рдХрд░рдиреЗ рдХрд╛ рдореМрдХрд╛ рд╣реИред


рдКрдкрд░ рдХреА рддрд╕реНрд╡реАрд░ рдореЗрдВ, рд▓рд╛рд▓ рдЙрд╕ рд╕рдордп рдХреЛ рдЗрдВрдЧрд┐рдд рдХрд░рддрд╛ рд╣реИ рдЬрдм рдкреНрд░рддреНрдпреЗрдХ рдЧреНрд░рд╛рд╣рдХ рд╕реЗрд╡рд┐рдд рдирд╣реАрдВ рдерд╛ред
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рдЪрд┐рддреНрд░ рд╕реЗ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдХреНрд▓рд╛рдЗрдВрдЯ рдП рдХреЛ рдХреБрдЫ рд╕рдордп рдкрд╣рд▓реЗ рдПрдХ рдЕрдиреБрд░реЛрдз рдкреНрд░рддрд┐рдмрдВрдз рдкреНрд░рд╛рдкреНрдд рд╣реБрдЖ рдФрд░ рдЙрдиреНрд╣реЗрдВ рдЕрдм рдФрд░ рдирд╣реАрдВ рднреЗрдЬрд╛ рдЧрдпрд╛, рдХреНрд▓рд╛рдЗрдВрдЯ рдмреА рдЪреБрдкрдЪрд╛рдк рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ рдФрд░ рд╕реАрдорд╛ рд╕реЗ рдЕрдзрд┐рдХ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдмреА рдиреЗ рдлрд┐рд▓рд╣рд╛рд▓ рдЕрдиреБрд░реЛрдз рд╕реАрдорд╛ рдХрд╛ рдЪрдпрди рдХрд┐рдпрд╛ рд╣реИ рдФрд░ рд░рд┐рдлреНрдпреВрдЬрд╝рд▓ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд░рд╣рд╛ рд╣реИред

рд╣рдо рдЧреНрд░рд╛рд╣рдХ рд╕реЗ рдЕрдиреБрд░реЛрдз рдХреЗ рд░реВрдк рдореЗрдВ рдЯреЛрдХрд░рд┐рдпрд╛рдБ рдмрдирд╛рдПрдВрдЧреЗ, рдФрд░ рд╕рдордп рдХреЛ рдзреНрдпрд╛рди рдореЗрдВ рд░рдЦреЗрдВрдЧреЗред рдкреНрд░рддреНрдпреЗрдХ рдЧреНрд░рд╛рд╣рдХ рдХрд╛ рдЕрдкрдирд╛ рд╕рдордп рдкреИрдорд╛рдирд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЯреЛрдХрд░реА рдХреЛ рдЬреАрд╡рди рднрд░ рдкрдврд╝ рд╕рдХрддреЗ рд╣реИрдВред рдЯреЛрдХрд░реА рдХреА рдорд╛рддреНрд░рд╛, рдЕрд░реНрдерд╛рддреН рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕реАрдорд╛, рдкреНрд░рддреНрдпреЗрдХ рдЧреНрд░рд╛рд╣рдХ рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ рд╕реЗ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХреА рдЬрд╛ рд╕рдХрддреА рд╣реИред

рд╣рдо рдбрд┐рдХреНрд╢рдирд░реА рдореЗрдВ рдЧреНрд░рд╛рд╣рдХ рдмрд╛рд╕реНрдХреЗрдЯ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рд╕реНрдЯреЛрд░ рдХрд░реЗрдВрдЧреЗ:
рдХреБрдВрдЬреА рдХреЗ рд░реВрдк рдореЗрдВ IP + тДЦ
counter - рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдЕрдиреБрд░реЛрдз рдХрд╛рдЙрдВрдЯрд░

рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЗ рд▓рд┐рдП API рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди check_rate(IP, TimeScale, Limit) ред
рдЬрд╣рд╛рдБ
IP рдЧреНрд░рд╛рд╣рдХ рдХрд╛ рдЖрдИрдкреА рдкрддрд╛ рд╣реИ (рд╣рд╛рд▓рд╛рдВрдХрд┐, рдпрд╣ рдХрд┐рд╕реА рднреА рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдХрд╛ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ)
TimeScale - рдЯреЛрдХрд░реА рдЬреАрд╡рдирдХрд╛рд▓ рдПрдордПрд╕ рдореЗрдВред
Limit - рдЯреЛрдХрд░реА рдореЗрдВ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рдЕрдзрд┐рдХрддрдо рд╕рдВрдЦреНрдпрд╛

рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рдиреЗ рд╕реЗ рдХрд╛рдЙрдВрдЯрд░ рдмрдврд╝ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдХреНрд▓рд╛рдЗрдВрдЯ рдХреЛ рд╡рд╛рдкрд╕ рдЖрддрд╛ рд╣реИ рдХрд┐ рдХреНрдпрд╛ рдЕрдиреБрд░реЛрдз рд╕реЗрд╡рд┐рдд рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред

рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди

рдбреЗрдЯрд╛ рд╕реНрдЯреЛрд░ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдореИрдВ ordered_set рдХрд╛ ETS рдЯреЗрдмрд▓ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд░рддрд╛ ordered_set ред рдпрд╣ рдХреБрдВрдЬреА рджреНрд╡рд╛рд░рд╛ рд╕реЙрд░реНрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ рдФрд░ рдбреБрдкреНрд▓рд┐рдХреЗрдЯ рдХреБрдВрдЬреА рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИред рддрд╛рд▓рд┐рдХрд╛ рдПрдХ рд░рд┐рдХреЙрд░реНрдб рд╣реИ
 [BucketID, Counter, CreatedAt, ModifiedAt] 

рдЬрд╣рд╛рдБ
BucketID - {IP, BucketNum}, рдСрд░реНрдбрд░_рд╕реЗрдЯ рдХреА рдХреБрдВрдЬреА рднреА рд╣реИ
Counter - рдЧреНрд░рд╛рд╣рдХ рд╕реЗ рдЕрдиреБрд░реЛрдзреЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛
CreatedAt - рдЯреЛрдХрд░реА рдмрдирд╛рдиреЗ рдХрд╛ рд╕рдордп (ms рдореЗрдВ)
ModifiedAt - рдЧрд╛рдбрд╝реА рдмрджрд▓рдиреЗ рдХрд╛ рд╕рдордп (рдПрдордПрд╕ рдореЗрдВ)
рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрдорд╛рдг рдХрд╛ рд╕рдордп рдЕрдзрд┐рдХ рд╣реИ, рдЖрдк рдЗрд╕реЗ рдордирд╛ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ

рдореБрдЦреНрдп рд╕рдорд╛рд░реЛрд╣:
 -spec count_hit(Id::binary(), Scale::integer(), Limit::integer()) -> {ok, continue} | {fail, Count::integer()}. %% Counts request by ID and blocks it if rate limiter fires %% ID of the client %% Scale of time (1000 = new bucket every second, 60000 = bucket every minute) %% Limit - max size of bucket count_hit(Id, Scale, Limit) -> Stamp = timestamp(), %% milliseconds since 00:00 GMT, January 1, 1970 BucketNumber = trunc(Stamp / Scale), %% with scale=1 bucket changes every millisecond Key = {BucketNumber, Id}, case ets:member(?RATERLIMITER_TABLE, Key) of false -> ets:insert(?RATERLIMITER_TABLE, {Key, 1, Stamp, Stamp }), {ok, continue}; true -> % increment counter by 1, created_time by 0, and changed_time by current one Counters = ets:update_counter(?RATERLIMITER_TABLE, Key, [{2,1},{3,0},{4,1,0, Stamp}]), % Counter, created at, changed at [BucketSize, _, _] = Counters, if (BucketSize > Limit) -> {fail, Limit}; true -> {ok, continue} end end. 


рдкрд╣рд▓реЗ, рдЬрд╛рдВрдЪреЗрдВ рдХрд┐ рдХреНрдпрд╛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЯреЛрдХрд░реА {рдЖрдИрдкреА, рдмрдХреЗрдЯрдирдВрдмрд░} рд╣реИред
рдПрдХ рдирдИ рдЯреЛрдХрд░реА рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╕рдм рдХреБрдЫ рдмрд╣реБрдд рд╕реБрдВрджрд░ рд╣реИ - рдкреНрд░рд╛рд░рдВрднрд┐рдХ рдорд╛рдиреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдирдИ рдЯреЛрдХрд░реА рдмрдирд╛рдПрдВ рдФрд░ рдареАрдХ рдХрд╣реЗрдВред

рдореМрдЬреВрджрд╛ рдЯреЛрдХрд░реА рдореЗрдВ рдПрдХ рдХрд╛рдЙрдВрдЯрд░ рдЬреЛрдбрд╝рдирд╛ рдереЛрдбрд╝рд╛ рдЕрдзрд┐рдХ рджрд┐рд▓рдЪрд╕реНрдк рд╣реИред рдИрдЯреАрдПрд╕ рдореЙрдбреНрдпреВрд▓ рдЖрдкрдХреЛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдирд┐рдпрдореЛрдВ рдХреЗ рдЕрдиреБрд╕рд╛рд░ рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреЛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред рдореБрдЭреЗ рдпрд╣ рдкрд╕рдВрдж рдЖрдпрд╛ рдХрд┐ рдЕрдВрддрд┐рдо рдХреЙрд▓ рдХреА рддрд╛рд░реАрдЦ рдореЗрдВ рдмрджрд▓рд╛рд╡ рдХреЗ рд╕рд╛рде рдЖрдк рдХрд╛рдЙрдВрдЯрд░ рдХреЗ рд╡реЗрддрди рд╡реГрджреНрдзрд┐ рдХреЛ рдХреИрд╕реЗ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред

рддреЛ рдХреЛрдб:
  Counters = ets:update_counter(?RATERLIMITER_TABLE, Key, [{2,1},{3,0},{4,1,0, Stamp}]) 


рдЗрдВрдХреНрд░реАрдореЗрдВрдЯ рдХрд╛рдЙрдВрдЯрд░ рдирдВрдмрд░ 2 рдмрд╛рдп 1 (рдпрд╣ рд╕рд┐рд░реНрдл рд╣рд┐рдЯ рдХрд╛рдЙрдВрдЯрд░ рд╣реИ), рд╕реГрдЬрди рдХреЗ рд╕рдордп рдореЗрдВ 0 рдЬреЛрдбрд╝реЗрдВ, рдЕрдзрд┐рдХрддрдо рдореВрд▓реНрдп рдХреА рдЬрд╛рдВрдЪ рдХреЗ рд╕рд╛рде 1 рд╕реЗ рдХрд╛рдЙрдВрдЯрд░ рдирдВрдмрд░ 4 рдореЗрдВ рдЬреЛрдбрд╝реЗрдВред рдХреНрдпреЛрдВрдХрд┐ рдЕрдзрд┐рдХрддрдо рдорд╛рди 0 рд╣реИ, рдЪреМрдерд╛ рдХрд╛рдЙрдВрдЯрд░ рд╣рдореЗрд╢рд╛ рд╕реНрдЯреИрдореНрдк (рд╡рд░реНрддрдорд╛рди рд╕рдордп) рдкрд░ рд╕реЗрдЯ рд╣реИред рдЖрдЙрдЯрдкреБрдЯ рдкрд░, рд╣рдореЗрдВ рдХреНрд░рдо рдореЗрдВ рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрдиреАрдп рдХрд╛рдЙрдВрдЯрд░реЛрдВ рдХреА рдПрдХ рд╕реВрдЪреА рдорд┐рд▓рддреА рд╣реИ, рдЕрд░реНрдерд╛рддред

[Counter, CreatedTime, ChangedTime]

рдирддреАрдЬрддрди, рдЯреЗрдмрд▓ рдкрд░ рджреЛ рдХреЙрд▓ рдХреЗ рд▓рд┐рдП, рд╣рдордиреЗ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдпрд╛ рдПрдХ рдЯреЛрдХрд░реА рдмрдирд╛рдИ рдФрд░ рдЖрдЙрдЯрдкреБрдЯ рдкрд░ рдХреЙрд▓ рдХреА рд╕рдВрдЦреНрдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХреАред рд╡рд░реНрддрдорд╛рди raterlimiter рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ , рдмрджрд▓рддреЗ рддрд╛рд▓рд┐рдХрд╛рдУрдВ рдХреА рдкрд░рдорд╛рдгреБрддрд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рдирд╣реАрдВ рд╣реИ, рдпрд╣ рдХреЗрд╡рд▓ рд╕рд┐рдВрдХреНрд░реЛрдирд╕ (рдХреЙрд▓рд┐рдВрдЧ gen_server: call / 2 рд╕рд┐рдВрдХреНрд░реЛрдирд╕ рд╣реИ)ред

рдкреБрд░рд╛рдиреЗ рдХреВрдбрд╝реЗрджрд╛рди рдХреЛ рд╣рдЯрд╛рдирд╛

рд╕рдордп рдХреЗ рд╕рд╛рде, рдЧреНрд░рд╛рд╣рдХ рд╕рднреА рдвреЗрд░ рдХреЛ рдвреЗрд░ рдХрд░ рджреЗрддреЗ рд╣реИрдВ рдФрд░ рдвреЗрд░ рдХрд░ рджреЗрддреЗ рд╣реИрдВред рдЗрдиреНрд╣реЗрдВ рд╣рдЯрд╛рдирд╛ рдЬрд░реВрд░реА рд╣реИред

рдирд┐рдХрд╛рд▓рдирд╛ рд╕рдордп-рд╕рдордп рдкрд░ рд╣реЛрддрд╛ рд╣реИред рдмрд╕, рдирд┐рд░реНрджрд┐рд╖реНрдЯ рд╕реАрдорд╛ рд╕реЗ рдЕрдзрд┐рдХ рдкреБрд░рд╛рдиреЗ рд╕рднреА рдмрд╛рд╕реНрдХреЗрдЯ рд╣рдЯрд╛ рджрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред

рдореБрдЭреЗ рдХрд╣рдирд╛ рд╣реЛрдЧрд╛ рдХрд┐ рдПрд░реНрд▓реИрдВрдЧ рдкрд░ рд╕рдм рдХреБрдЫ рд╕реБрдВрджрд░ рдФрд░ рд╕рдВрдХреНрд╖рд┐рдкреНрдд рд▓рдЧрддрд╛ рд╣реИ -
 remove_old_limiters(Timeout) -> NowStamp = timestamp(), Matcher = ets:fun2ms(fun ({_,_,_,Accessed}) when Accessed < (NowStamp - Timeout) -> true end), ets:select_delete(?RATERLIMITER_TABLE, Matcher). 


ets: select_delete рдореИрдЪ рдлрд╝рдВрдХреНрд╢рди ( MatchSpec ) рд╕реЗ рдореЗрд▓ рдЦрд╛рддреЗ рд╕рднреА рд░рд┐рдХреЙрд░реНрдб рдорд┐рдЯрд╛ рджреЗрддрд╛ рд╣реИред рдореИрдиреНрдпреБрдЕрд▓ рд░реВрдк рд╕реЗ рдЗрди match_spec рдХреЛ рд▓рд┐рдЦрдирд╛ рдирд░рдХ рд╣реИред рдИрдЯреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реИ : fun2ms рдлрд╝рдВрдХреНрд╢рди , рдЬреЛ рдирд┐рдпрдорд┐рдд рдПрд░реНрд▓реИрдВрдЧ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкрддреНрд░рд╛рдЪрд╛рд░ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддрд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЙрдкрд░реЛрдХреНрдд рдлрд╝рдВрдХреНрд╢рди

 fun ({_,_,_,Accessed}) when Accessed < (NowStamp - Timeout) -> true end 


рдореИрдЪрд╕реНрдЯреЗрдХ рдкреНрд░рд╛рд░реВрдк рдореЗрдВ рдЕрдВрддрд┐рдо рд░реВрдк рдореЗрдВ, NowStamp = 1000 рдХреЗ рд▓рд┐рдП, рдЯрд╛рдЗрдордЖрдЙрдЯ = 0 рджрд┐рдЦрддрд╛ рд╣реИ

 [{{'_','_','_','$1'},[{'<','$1',{'-',1000,0}}],[true]}] 


рдИрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╕рдордп рдореБрдЦреНрдп рдмрд╛рдд: fun2ms рд╕реНрд░реЛрдд рдореЗрдВ рдПрдХ рдЕрддрд┐рд░рд┐рдХреНрдд рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рдирд╛ рдирд╣реАрдВ рднреВрд▓рдирд╛ рд╣реИ -

 -include_lib("stdlib/include/ms_transform.hrl"). 


рдХреЗ рдЙрдкрдпреЛрдЧ

рдЪреЗрдХ_рдЯреНрд░реЗрдб рдкрд░ рдПрдХ рдХреЙрд▓ рдореЗрдВ рдЙрдкрдпреЛрдЧ рдХрдо рд╣реЛ рдЬрд╛рддрд╛ рд╣реИ, рдЧрд┐рдирддреА рдирд╣реАрдВ, рдЬрд╝рд╛рд╣рд┐рд░ рд╣реИ, рдХреЛрдб рдФрд░ рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХреЛ рд░реИрдЯреНрд▓рд┐рдорд┐рдЯрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рд▓реЙрдиреНрдЪ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдПред рдпрд╣рд╛рдБ рдореЗрд░реЗ Mochiweb рдЖрдзрд╛рд░рд┐рдд рдЕрдиреБрдкреНрд░рдпреЛрдЧ рд╕реЗ рдПрдХ рдЙрджрд╛рд╣рд░рдг рд╣реИ:

  {Status, _Reason} = raterlimiter:check_rate(Req:get(peer), 30000, 500), % 500 requests per 30 seconds allowed case Status of ok -> serve_request(Req, DocRoot, Path); _ -> % client wants too much information Req:respond({413,[{"Content-Type", "text/html"}, {"Retry-After", "900 (Too many requests)"}], "  IP   ,  15 ."}) end 


рдкреВрд░рд╛ рдХреЛрдб рдЬреАрдердм рдкрд░ рдЙрдкрд▓рдмреНрдз рд╣реИред рд╡рд╣рд╛рдВ рдЖрдк рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд░рд┐рдкреЛрд░реНрдЯ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╛ рдкреБрд▓ рдЕрдиреБрд░реЛрдз рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред

Source: https://habr.com/ru/post/In145105/


All Articles