> On Jun 24, 2019, at 8:33 PM, Dk Jack <dnj0...@gmail.com> wrote:
>
> I suspect connection pools would be using the http pipeline feature to
> multiplex multiple client connections on to the pool connections towards
> ATS.
Right. But, you can turn off the pipelining support on ATS, if there isn’t a
clear benefit (particularly, true if your client is a CDN which can already
leverage connection pools).
> In my case, rate-limiting was implemented as a security feature i.e
> rate-limiting malicious IPs etc. Moreover, we don't have control over it at
> the entry point... since most of the time we have to look at the requests
> at the http level (sometimes even into the bodies) to figure if we should
> apply rate-limiting or not...
>
> On Mon, Jun 24, 2019 at 7:28 PM Sudheer Vinukonda
> <sudheervinuko...@yahoo.com.invalid> wrote:
>
>> Interesting setup - But, wouldn’t the CDN have connection pools to ATS
>> already? Curious to know if enabling HTTP pipelining provides benefits
>> beyond what connection pools can give.
>>
>> That said, I don’t think it makes a lot of sense to implement rate
>> limiting for _end clients_ in this sort of a setup. Typically, you’d want
>> to rate limit at the entry point of the user traffic, which means the rate
>> limiting for end users would be done at the CDN in this setup. You could
>> still add rate limiting for the CDN itself but yes in that case it makes
>> sense to just reject the requests and let the CDN retry.
>>
>> @Weixi Li,
>>
>> The more I read about your use case, it seems like you could probably
>> directly leverage the rate limiting that ATS core already supports (unless
>> you’ve other custom requirements). You can configure the below settings per
>> origin service in your remap config, and you should get the behavior your
>> use case described.
>>
>>
>> proxy.config.http.per_server.connection.max
>> Scope
>> CONFIG
>> Type
>> INT
>> Default
>> 0
>> Reloadable
>> Yes
>> Overridable
>> Yes
>> Set a limit for the number of concurrent connections to an upstream server
>> group. A value of 0 disables checking. If a transaction attempts to connect
>> to a group which already has the maximum number of concurrent connections
>> the transaction either rechecks after a delay or a 503
>> (HTTP_STATUS_SERVICE_UNAVAILABLE) error response is sent to the user agent.
>> To configure
>>
>> Number of transactions that can be delayed concurrently
>> See proxy.config.http.per_server.connection.queue_size.
>>
>> How long to delay before rechecking
>> See proxy.config.http.per_server.connection.queue_delay.
>>
>> Upstream server group definition
>>
>>
>>
>>> On Jun 24, 2019, at 6:58 PM, Dk Jack <dnj0...@gmail.com> wrote:
>>>
>>> Leif,
>>> I was talking about the case where ATS is deployed after CDN.
>>>
>>> client --> CDN Network -------> ATS --> Origin-Server
>>>
>>> In most such deployments, the connection between the CDN and ATS is HTTP
>>> 1.1. and it is pipelined. In that case, you cannot stall the clients
>>> because you could run into head-of-line blocking situation.
>>>
>>>
>>>> On Mon, Jun 24, 2019 at 4:07 PM Leif Hedstrom <zw...@apache.org> wrote:
>>>>
>>>> You definitely would not want to stall the client after you’ve made an
>>>> origin connection. I.e. you only want to stall the UA.
>>>>
>>>> — Leif
>>>>
>>>>> On Jun 24, 2019, at 14:42, Dk Jack <dnj0...@gmail.com> wrote:
>>>>>
>>>>> Also, stalling will not be good, if you have CDN upstream from you that
>>>> is pipelining requests on the same connection for multiple clients. In
>> our
>>>> plugin we tried delay request, but we couldn’t solve http 1.1 pipeline
>>>> issue. Hence ended up going with the simple approach of deny.
>>>>>
>>>>> Dk.
>>>>>
>>>>>> On Jun 24, 2019, at 1:12 PM, Leif Hedstrom <zw...@apache.org> wrote:
>>>>>>
>>>>>>
>>>>>>
>>>>>>> On Jun 24, 2019, at 13:12, Weixi Li (BLOOMBERG/ PRINCETON) <
>>>> wli...@bloomberg.net> wrote:
>>>>>>>
>>>>>>> Hi Dk,
>>>>>>>
>>>>>>> Thanks a lot for the example. It is really inspiring. I have a
>>>> question though: in case of "bucket->consume()" returning false, the
>> code
>>>> would return a 429 response. In our use-case, we don't want to deny the
>>>> client with a 429 (but want to queue the request instead). How to handle
>>>> the false case then? Should addPlugin() add the plugin itself? (That's
>> why
>>>> I was asking about queue and async timer).
>>>>>>
>>>>>> Oh do you want to stall the client, not deny? Depending on the plugin
>>>> and the hook, you can probably just reschedule the HttpSM to come back
>> on
>>>> say 500ms and try again, rather than let it continue like you normally
>>>> would. Have to make sure they don’t stall fore ever though, and perhaps
>>>> have a priority such that older clients are given tokens before new
>> ones.
>>>>>>
>>>>>> Should be doable, but definitely more complex.
>>>>>>
>>>>>> — Leif
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Weixi
>>>>>>>
>>>>>>> From: dev@trafficserver.apache.org At: 06/24/19 01:28:40To: Weixi
>> Li
>>>> (BLOOMBERG/ PRINCETON ) , dev@trafficserver.apache.org
>>>>>>> Subject: Re: Implementing Rate-limiting in forward proxy mode
>>>>>>>
>>>>>>> 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
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>
>>>>
>>>>
>>