Volanie Configurator->createContainer() robí sleep() blokujúcou
- martin.palenik
- Člen | 3
Nasledovný minimal working example demonštruje problém, s ktorým sa
potýkam. Funkcia sleep()
je v kóde blokujúca, čiže všetky
ostatné požiadavky musia počkať kým prejde 10 sekúnd. Po zakomentovaní
uvedených dvoch riadkov, ale sleep()
už blokujúca nie je, čo je
to čo chcem.
mwe.php
<?php
require __DIR__ . '/vendor/autoload.php';
$configurator = App\Bootstrap::boot(); // Does not make sleep() blocking, provided debug mode is disabled.
$container = $configurator->createContainer(); // Makes sleep() blocking. Disabling debug mode and Tracy has no effect. Removing this line makes sleep() not blocking.
sleep(10);
Bootstrap.php
<?php
namespace App;
use Nette\Bootstrap\Configurator;
use Tracy\BlueScreen;
class Bootstrap
{
public static function boot(): Configurator
{
$appDir = dirname(__DIR__);
$configurator = new Configurator();
$configurator->setDebugMode(false);
$configurator->setTimeZone('Europe/Prague');
/*
$logDir = $appDir . "/log";
if (!is_dir($logDir) && !mkdir($logDir)) {
if ($configurator->isDebugMode()) {
$blueScreen = new BlueScreen();
$blueScreen->render(new \Exception("Cannot create log directory at $logDir. Tracy debugger cannot log errors."));
}
}
$configurator->enableTracy($appDir . "/log");*/
$configurator->setTempDirectory($appDir . "/temp");
$configurator->addConfig($appDir . '/config/services.neon');
return $configurator;
}
}
composer.json
{
"autoload": {
"psr-4": {
"App\\": "app/",
"DatabaseGateways\\": "DatabaseGateways/",
"Parser\\": "Parser/"
},
"files": [
"Controller.php",
"Database.php",
"DatabaseGateway.php",
"ErrorHandler.php",
"Scheduler.php"
]
},
"require": {
"ext-pdo": "*",
"php": "^8.2.1 <8.4",
"nette/bootstrap": "^3.2",
"tracy/tracy": "^2.10",
"nette/security": "^3.2",
"nette/http": "^3.3"
},
"config": {
"platform": {
"php": "8.2.1"
}
},
"prefer-stable": true
}
Prečo Nette robí funkciu blokujúcou a ako to obísť, aby neblokovala ďalšie požiadavky?
- Kamil Valenta
- Člen | 815
martin.palenik napsal(a):
čiže všetky ostatné požiadavky musia počkať
Jsi si jist, že všechny ostatní? Nebo jen „tvoje ostatní“? Myslím, že jiný client, v jiném vlákně php, čekat nebude…
Prečo Nette robí funkciu blokujúcou a ako to obísť, aby neblokovala ďalšie požiadavky?
Nestartuješ v requestech sessionu?
- martin.palenik
- Člen | 3
Nestartuješ v requestech sessionu?
Neviem, ako to zistím? Problém spôsobuje už priložený
mwe.php
.
Jsi si jist, že všechny ostatní? Nebo jen „tvoje ostatní“? Myslím, že jiný client, v jiném vlákně php, čekat nebude…
Musia čakať všetci, ktorí sú prihlásení v danom prehliadači v rôznych taboch. Ak sa súčasne prihlásim aj inde, napríklad do Firefoxu, tak tam čakať spravidla nemusím, ale po istom čase aj ten začína blokovať. Ale len kým bežá sleep() a hneď ako dobehne tak sa požiadavky dokončia.
Na WEDOS je obmedzenie na 30 procesov, ktoré môžu bežať zároveň, a z podpory mi písali, že sme to prekročili. Či to ale súviselo práve s týmto, to si nie som istý.
Editoval martin.palenik (30. 7. 15:31)
- nightfish
- Člen | 516
martin.palenik napsal(a):
Musia čakať všetci, ktorí sú prihlásení v danom prehliadači v rôznych taboch.
Ak sa súčasne prihlásim aj inde, napríklad do Firefoxu, tak tam čakať spravidla nemusím, ale po istom čase aj ten začína blokovať.
@martinpalenik
To mi vskutku zní jako problém zamykání sessions. Viz třeba https://forum.nette.org/…ich-requestu
- Kamil Valenta
- Člen | 815
Requesty, které sahají do sessiony (což pro přihlášené uživatele
určitě děláš) se nevykonají asynchronně, to nemá společného nic
s Nette. U sessiony se vytvoří zámek a dokud se neuvolní (např.
doběhnutím skriptu), ostatní čekají v řadě. Řešením může být:
neotvírat sessionu, dokud to skutečně není nevyhnutelně potřeba. Zavřít
sessionu ihned, jakmile už potřeba není. Nebo handler na jinou storage.
Když budeš googlit session blocking, určitě najdeš mnoho příkladů a
plusy i mínusy jednotlivých variant.
- martin.palenik
- Člen | 3
Mali ste pravdu, bol to problém session lockingu. Riešením bolo predtým
zavolať session_write_close()
. Napriek tomu, toto riešenie
nefunguje v debug móde.
$configurator = new Configurator();
$configurator->setDebugMode(true);
Neviete prečo?
Tu je kód pre ilustráciu:
require __DIR__ . '/vendor/autoload.php';
$configurator = App\Bootstrap::boot(); // Does not make sleep() blocking, provided debug mode is disabled.
file_put_contents(__DIR__ . '/container.log', "Before createContainer: " . session_status() . "\n"); // Before createContainer: 1
$container = $configurator->createContainer(); // Makes sleep() blocking. Disabling debug mode and Tracy has no effect. Removing this line makes sleep() not blocking.
file_put_contents(__DIR__ . '/container.log', "After createContainer: " . session_status() . "\n", FILE_APPEND); // After createContainer: 2
if (session_status() === PHP_SESSION_ACTIVE) {
session_write_close();
}
sleep(10);
// Reopen the session if necessary
if (session_status() !== PHP_SESSION_ACTIVE) {
file_put_contents(__DIR__ . '/container.log', "Starting new session" . "\n", FILE_APPEND);
file_put_contents(__DIR__ . '/container.log', "Starting new session - session_status() before: " . session_status() . "\n", FILE_APPEND); // Starting new session - session_status() before: 1
session_start();
file_put_contents(__DIR__ . '/container.log', "Starting new session - session_status() after: " . session_status() . "\n", FILE_APPEND); // Starting new session - session_status() after: 2
}
Editoval martin.palenik (5. 9. 9:26)