laravel / octane

Supercharge your Laravel application's performance.
https://laravel.com/docs/octane
MIT License
3.73k stars 289 forks source link

Octane doesn't drop connections after docker container stopped #851

Closed Focusnik closed 4 months ago

Focusnik commented 4 months ago

Octane Version

latest

Laravel Version

11.0.5

PHP Version

8.3

What server type are you using?

Open Swoole

Server Version

docker latest

Database Driver & Version

Mysql 8.3.0

Description

We have a setup with docker + jenkins. When docker stops and starts a new container, the MySQL connection from the old container is still working.

After some time and several reboots, we use up all max_connections in the mysql container.

How i can handle this out?

By the way, php artisan octane:start --workers=2 --task-workers=2 --host=0.0.0.0 should spawn 4 connections, i believe, but in my test, it spawn ~10

We can play with global variable in MySql, such as wait_timeout to force it close connection, but i want to discuss some other solutions, if such exist

Steps To Reproduce

  1. Setup mysql container via docker
  2. Setup php container with openswoole and run it through php artisan octane:start --workers=2 --task-workers=2 --host=0.0.0.0
  3. Use docker stop, rm and then up a new container.
  4. Check PROCESSLIST in mysql, there will be old and new one connections.
Focusnik commented 4 months ago

Another way to check the bug:

  1. Run octane in terminal
  2. Close the terminal
  3. Connections still there until i call php artisan octane:stop

In case of docker, we are stopping whole system that run octane. We found tip, how we can handle that in docker:

docker-entrypoint.sh

#!/bin/bash

# Function to handle the SIGTERM signal
_term() {
  echo "Caught SIGTERM signal!"
  # Execute any command before shutdown
  echo "Stopping Laravel Octane gracefully..."
  php artisan octane:stop

  exit 0
}

# Trap the SIGTERM signal and link it to the _term function
trap _term SIGTERM

# Your original CMD commands, moved to the background
php artisan octane:start --workers=2 --task-workers=2 --host=0.0.0.0 &

# Grab the last background process's PID
pid=$!

# Wait for this process to end
wait $pid

But docker sigterm is unstable, and we afraid that we will have problems in AWS ECR or Kubernetes (but kub, also has ability to run scripts before termination)...

We need ability to close octane with parent process, if that can be done. Or maybe you have other solutions <3

Focusnik commented 4 months ago

i've already tried this config, but it won't close the process, when parent process closed....

[
'swoole' => [
        'mode' => SWOOLE_BASE,
        'options' => [
            'daemonize' => 0
        ]
    ],
]
Focusnik commented 4 months ago

I figure out, that all commands should be extended with SIGHUP

/**
 * Returns the list of signals to subscribe.
 */
public function getSubscribedSignals() : array
{
    return [ SIGINT, SIGTERM, SIGHUP ];
}

In that case, server will be stopped, while docker rip bash/sh terminal with sigterm

driesvints commented 4 months ago

Nice that you found a solution. Could you try and PR That? Thanks!