Not sure you need queues. Here's a sample implementation based on TokenBucket which should do what you want...
void handleReadRequestHeadersPreRemap(Transaction& transaction) { std::string host; Headers& headers = transaction.getClientRequest().getHeaders(); Headers::iterator ii = headers.find("Host"); if (ii != headers.end()) { host = (*ii).values(); } if (!host.empty()) { auto bucket = map.find(host); // assumes u created a token bucket per site. // std::map<std::string, std::shared_ptr<TokenBucket>> // map.emplace("www.cnn.com", // std::make_shred< TokenBucket>(rate, burst)); // rate is number of req.s/min. // burst can be same as rate. if (bucket->consume(1)) { // you are requesting 1 token. transaction.resume(); } else { // see CustomResponseTransactionPlugin in atscppapi examples. transaction.addPlugin(new CustomResponseTransactionPlugin(transaction, 429, "Too Many Requests", "Too Many Requests")); return; } } transaction.resume(); } On Sun, Jun 23, 2019 at 8:04 PM Weixi Li (BLOOMBERG/ PRINCETON) < wli...@bloomberg.net> wrote: > Hi Dk/Eric/Leif, > > Thanks for the advice. Our use-case simply requires sending out the queued > requests at a fixed rate (although variable by site). My plan was simply > put all incoming transactions in separate queues by site, and then invoke > "transaction.resume()" at fixed interval via a timer for each queue. Would > the delay (calling "transaction.resume()" asynchronously) disrupt the ATS > event processing? If yes, what's correct way to avoid that? If no, is there > any example plugin implementing such a timer (was thinking about AsyncTimer > in atscppapi)? > > The TokenBucket is a very interesting data structure, but I've not figured > out how to apply it yet. Will look into it a bit more. > > Thanks to Eric's point, TS_HTTP_SEND_REQUEST_HDR_HOOK will indeed be too > late. But for this use-case the "rate-limit" only applies to cache-misses > and revalidations (fresh cache-hits should be served as fast as possible). > Therefore the hook probably should be TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK. > The plugin then lets the transaction resume immediately if the cache hit is > fresh, or queue the transaction otherwise. > > Still learning ATS, let me know if I'm wrong. Thanks! > > > From: dev@trafficserver.apache.org At: 06/21/19 23:11:03To: Weixi Li > (BLOOMBERG/ PRINCETON ) , dev@trafficserver.apache.org > Subject: Re: Implementing Rate-limiting in forward proxy mode > > Uhm! why async timers? You'd want to implement a leaky/token bucket per > site. Check out... > > https://github.com/rigtorp/TokenBucket > > It's single header file lock free implementation for token bucket and it > works very well... > > > On Fri, Jun 21, 2019 at 7:38 PM Weixi Li (BLOOMBERG/ PRINCETON) < > wli...@bloomberg.net> wrote: > > > What a great community! So many good tips in such a short time! > > > > Especially the atscppai, I would've never noticed it. the async examples > > look very promising. > > > > It looks like the following might be necessary (let me know if I'm > wrong): > > * A hook to TS_HTTP_SEND_REQUEST_HDR_HOOK > > * A map of queues (one queue per rate-limited site) > > * A map of async timers (one timer per queue) > > > > I will study the ATS code more to understand the event and threading > model > > better. > > > > Thank you all. > > > > From: dev@trafficserver.apache.org At: 06/21/19 19:52:44To: > > dev@trafficserver.apache.org > > Subject: Re: Implementing Rate-limiting in forward proxy mode > > > > I have implemented rate-limit in my plugin using atscppapi. We are using > > ats in > > security context for mitigation. If the request matches certain criteria > > (ip, > > method, host, uri and header values) then we apply rate-limit to that ip. > > > > Dk. > > > > > On Jun 21, 2019, at 3:15 PM, Leif Hedstrom <zw...@apache.org> wrote: > > > > > > > > > > > >> On Jun 21, 2019, at 16:09, Weixi Li (BLOOMBERG/ PRINCETON) > > <wli...@bloomberg.net> wrote: > > >> > > >> Hi team, > > >> > > >> We are experimenting with ATS in *forward* proxy mode. Our use-case > > requires > > a rate-limiting component that enforces rules based on the destination. > > >> > > >> For example: > > >> > > >> For all incoming requests targeting "www.cnn.com", we want to limit > > the > > outgoing rate to be 10 requests per minute; for "www.reddit.com", we > want > > the > > rate to be 20 requests per minute; and so on. If there were more requests > > than > > the limit specified, the requests must be queued before they could go > out. > > > > > > Seems very straight forward to implement as a plugin. For example the > > geo_acl > > plugin might be a good start, since it limits access based on source IP. > > > > > > Would be interesting to hear more about your use case too, it’s always > > exciting to hear about different solutions that people use ATS for. Maybe > > at > > the next ATS summit? :-) > > > > > > Cheers, > > > > > > — Leif > > >> > > >> Is it possible to implement this requirement using a plugin? > > >> > > >> If not, we wouldn't mind forking the code and modifying whichever > parts > > that > > would be necessary. But which are the potentially relevant components? > > >> > > >> If any experts could give us some pointers on the design, that would > be > > really appreciated. > > >> > > >> Thanks, > > >> Weixi > > > > > > > > > > > >