Skip to content

Max execution time of request on http server #5183

@GuillaumeBrook

Description

@GuillaumeBrook

I know it has been asked some times already :
#4594
#3078

How can we implement a real max_execution_time that will free the worker.

One proposed solution was that :

$http->on(
    Constant::EVENT_REQUEST,
    function (Request $request, Response $response) use () {
        echo 'Http request started' . "\n";
        Timer::after(5000, function () use ($response) {
            $response->status(408);
            $response->end('Timeout');
            echo 'Timeout has been sent' . "\n";
        });

       // Actual code that take maybe forever somehow

        echo 'We reached the end' . "\n";
        $response->status(200);
        $response->end('The end');
    }
);

So indeed the client will receive a 408 timeout.
But the worker is still working and doing things right ? (things that will never reach the end user)

So another implementation could be :

$http->on(
    Constant::EVENT_REQUEST,
    function (Request $request, Response $response) {
        echo 'Http request started' . "\n";
        $killRequest = false;
        Timer::after(5000, function () use ($response, &$killRequest) {
            $response->status(408);
            $response->end('Timeout');
            echo 'Timeout has been sent' . "\n";
            $killRequest = true;
        });

        echo 'Step 1' . "\n";
        sleep(2); // code that takes 2s
        if ($killRequest) return;

        echo 'Step 2' . "\n";
        sleep(2); // code that takes 2s
        if ($killRequest) return;

        echo 'Step 3' . "\n";
        sleep(2); // code that takes 2s
        if ($killRequest) return; // we stop here

        echo 'Step 4' . "\n";
        sleep(2); // code that takes 2s
        if ($killRequest) return;

        echo 'Step 5' . "\n";
        sleep(2); // code that takes 2s
        if ($killRequest) return;


        echo 'We reached the end' . "\n";
        $response->status(200);
        $response->end('The end');
    }
);

The print will be

Http request started
Step 1
Step 2
Step 3
Timeout has been sent

OK that's fine, but that just impossible to do, because we are inside classes doing stuff.

I'm concerned about CPU usage, RAM usage and especially about the workers.

From my test with only 1 worker, if somehow I don't use the database proxy classes, the worker can only treat one request at a time.
Meaning the first request is processing, the second is waiting.
I did the same test with database proxy classes, the second request doesn't wait however.
But I'm still concerned, if somehow all workers are blocked and the server can't receive any new request.

Is this an option that could be implemented in swoole internals ? What do you think ?

(OpenSwoole implemented it but I'm not sure it really works : openswoole/ext-openswoole#136)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions