Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[FrameworkBundle][HttpClient] Add ThrottlingHttpClient to limit requests within a timeframe #53550

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 3, 2024

Conversation

HypeMC
Copy link
Contributor

@HypeMC HypeMC commented Jan 16, 2024

Q A
Branch? 7.1
Bug fix? no
New feature? yes
Deprecations? no
Issues -
License MIT

This PR adds a simple ThrottlingHttpClient to help with limiting the number of requests within a certain period.

Simple example, don't send more than 10 requests in 5 second:

framework:
    http_client:
        scoped_clients:
            ping.client:
                base_uri: 'http://localhost:8080'
                rate_limiter: http_throttling

    rate_limiter:
        http_throttling:
            policy: 'token_bucket'
            limit: 10
            rate: { interval: '5 seconds', amount: 10 }
#[AsCommand('app:ping')]
class PingCommand extends Command
{
    public function __construct(
        #[Target('ping.client')] private HttpClientInterface $httpClient,
    ) {
        parent::__construct();
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $requests = [];
        for ($i = 0; $i < 100; $i++) {
            $requests[] = $this->httpClient->request('GET', '/ping');
        }

        foreach ($requests as $request) {
            $output->writeln($request->getContent());
        }

        return Command::SUCCESS;
    }
}

Receiving controller:

#[AsController]
class PingController
{
    #[Route('/ping', name: 'app_ping')]
    public function __invoke(): Response
    {
        return new Response((new \DateTime())->format('Y-m-d\TH:i:s.u'));
    }
}

Output:

$ bin/console app:ping

2024-01-16T11:52:54.922597
2024-01-16T11:52:54.964851
2024-01-16T11:52:55.009504
2024-01-16T11:52:55.053986
2024-01-16T11:52:55.098267
2024-01-16T11:52:55.139621
2024-01-16T11:52:55.182769
2024-01-16T11:52:55.264433
2024-01-16T11:52:55.304775
2024-01-16T11:52:55.223805

2024-01-16T11:52:59.877858
2024-01-16T11:52:59.914724
2024-01-16T11:52:59.950610
2024-01-16T11:52:59.986818
2024-01-16T11:53:00.025638
2024-01-16T11:53:00.063687
2024-01-16T11:53:00.879850
2024-01-16T11:53:00.919651
2024-01-16T11:53:00.959273
2024-01-16T11:53:00.999381

2024-01-16T11:53:04.890126
2024-01-16T11:53:04.965116
2024-01-16T11:53:04.999916
2024-01-16T11:53:05.037780
2024-01-16T11:53:05.073999
2024-01-16T11:53:05.110241
2024-01-16T11:53:05.917045
2024-01-16T11:53:05.971672
2024-01-16T11:53:06.016025
2024-01-16T11:53:06.059220

2024-01-16T11:53:09.920092
2024-01-16T11:53:09.974757
2024-01-16T11:53:10.010406
2024-01-16T11:53:10.045790
2024-01-16T11:53:10.081749
2024-01-16T11:53:10.118100
2024-01-16T11:53:10.924485
2024-01-16T11:53:10.981094
2024-01-16T11:53:11.023935
2024-01-16T11:53:11.067210

...

@carsonbot carsonbot added this to the 7.1 milestone Jan 16, 2024
@HypeMC HypeMC force-pushed the add-throttling-httpclient branch 2 times, most recently from 8c8ad49 to e70c356 Compare January 16, 2024 12:02
@HypeMC HypeMC force-pushed the add-throttling-httpclient branch 3 times, most recently from 5b676f0 to e554083 Compare January 16, 2024 18:23
@HypeMC HypeMC force-pushed the add-throttling-httpclient branch 4 times, most recently from 27cfc2c to 8d43eb7 Compare January 22, 2024 11:40
@nicolas-grekas
Copy link
Member

Can you please help me get the steps that achieve the throttling? Which part is sleeping especially? The lock is, right?
Do we need to play with the pause handler then? I think this can be checked by comparing how curl vs native http clients behave with the current code.

@HypeMC
Copy link
Contributor Author

HypeMC commented Jan 23, 2024

@nicolas-grekas Actually no, $this->rateLimiter()->reserve()->getWaitDuration() doesn't sleep, it just returns the expected delay between the requests. The pause handler is what actually sleeps. This behavior is consistent across both the curl and native http clients. Maybe I'm wrong, but if the lock was what slept, then that would mean that the creation of the response objects was delayed, but not the actual requests which are triggered afterwards.

Copy link
Member

@nicolas-grekas nicolas-grekas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the insights, makes sense now.

@HypeMC HypeMC force-pushed the add-throttling-httpclient branch 2 times, most recently from 84c8927 to 1a8b068 Compare January 23, 2024 09:55
@fabpot fabpot force-pushed the add-throttling-httpclient branch from 1a8b068 to 5bb5474 Compare February 3, 2024 13:13
@fabpot
Copy link
Member

fabpot commented Feb 3, 2024

Thank you @HypeMC.

@fabpot fabpot merged commit f0f3040 into symfony:7.1 Feb 3, 2024
@HypeMC HypeMC deleted the add-throttling-httpclient branch February 3, 2024 14:10
@fabpot fabpot mentioned this pull request May 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants