BG Development


  Reply to this topicStart new topicStart Poll

> Fire and forget с fsockopen
emagi
Публикувано на: 05-05-2022, 11:04
Quote Post



Име:
Група: Потребител
Ранг: Редовен член

Мнения: 565
Регистриран на: 12.03.07



Здравейте,

следният казус: трябваше ми начин, по който да направя Rest2Rest комуникация, която да не влияе на основният Request. Имам API, в което ме интересува времето на изпълнение, кое IP е извикало следния ресурс, и т.н.
Чрез fsockopen изпращам асинхронно данните от текущия Request на друг, който записва тези Meta данни. Важното е, да изпратя заявката без да чакам отговора на тази заявка. Ако има грешки в обработката й, то ще бъде записа в лог файл, като това не влияе на основната логика.
Та и малко код:
CODE

public static function post_async(string $path, $params = array(), $debug = false): void
   {
       $post_string = json_encode($params);
       $fp = fsockopen($_SERVER['SERVER_ADDR'], $_SERVER['SERVER_PORT'], $errno, $errstr, 0.01);
       if (!$fp) {
           (Logger::GetInstance())->log("An error occurred while trying send request meta data: " . $errno . " - " . $errstr);
           return;
       }
       $request_uri = $_SERVER['REQUEST_SCHEME'] . "://" . $_SERVER['HTTP_HOST'] . $path;
       if ($debug) {
           $request_uri .= "?XDEBUG_SESSION_START=PHPSTORM";
       }
       // create output string
       $output  = "POST " . $request_uri . " HTTP/1.1\r\n";
       $output .= "Host: " . $_SERVER['HTTP_HOST'] . "\r\n";
       $output .= "Content-Type: application/json\r\n";
       $output .= "Content-Length: " . strlen($post_string) . "\r\n";
       $output .= "Connection: Close\r\n\r\n";
       $output .= isset($post_string) ? $post_string : '';
       fwrite($fp, $output);
       if ($debug) {
           (Logger::GetInstance())->log(fgets($fp));
       }
       fclose($fp);
   }


Та, какво ми е питането. Направи ми впечатление, че на локалния копютър всичко си е наред. Но когато upload-на кода на сървъра, той работи САМО когато извикам fgets($fp)
Това го забелязох, когато исках да видя, аджеба какво връща заявката и пуснах метода с параметър debug = true

Предполагам се дължи на някоя особеност, която ми убягва в момента.
Имате ли идеи на какво може да се дължи проблема?

Благодаря
PMEmail Poster
Top
thrawn
Публикувано на: 05-05-2022, 11:17
Quote Post



Име:
Група: Потребител
Ранг: Почетен член

Мнения: 3341
Регистриран на: 17.01.17



Кое му е асинхронното на това?

За да е асинхронно, "неблокиращата" заявка записва мета данните в споделен ресурс (база данни). След това се стартира отделен процес който чете мата данните от споделения ресурс и ги изпраща на другия сървиз.

Втория процес може да си е резидентрн (да работи постоянно във фонов режим), да се стартира периодично (с крон например) или явно, от "неблокиращия" скрипт.

Като цяло, тук излизаш от стандартния цикъл на живот на php приложенията и ще трябва да тъсиш специфично решение.
PMEmail Poster
Top
emagi
Публикувано на: 05-05-2022, 11:24
Quote Post



Име:
Група: Потребител
Ранг: Редовен член

Мнения: 565
Регистриран на: 12.03.07



QUOTE (thrawn @ 05-05-2022, 11:17)
Кое му е асинхронното на това?

За да е асинхронно, "неблокиращата" заявка записва мета данните в споделен ресурс (база данни). След това се стартира отделен процес който чете мата данните от споделения ресурс и ги изпраща на другия сървиз.

Втория процес може да си е резидентрн (да работи постоянно във фонов режим), да се стартира периодично (с крон например) или явно, от "неблокиращия" скрипт.

Като цяло, тук излизаш от стандартния цикъл на живот на php приложенията и ще трябва да тъсиш специфично решение.

Еми аз какво правя? Изпращям заявката, и оставям другата API да извърши нужните неща, без това да блокира основната логика, като НЕ чакам за отговор

Не бъркай паралелно, с асинхронно

Това мнение е било редактирано от emagi на 05-05-2022, 11:27
PMEmail Poster
Top
thrawn
Публикувано на: 05-05-2022, 11:30
Quote Post



Име:
Група: Потребител
Ранг: Почетен член

Мнения: 3341
Регистриран на: 17.01.17



icon_smile.gif асинхронност в рамките на една нишка се постига ако в нея има "цикъл за обработка на съобщения". Текущия код се обработва в текущата итерация а асинхронноя се поставя на опашка за обработка при някоя следваща итерация. Така получаваш неблокиращо поведение. PHP не предлага такава архитектура.

Това което правиш си е най-обикновено блокиращо извикване.

Това мнение е било редактирано от thrawn на 05-05-2022, 11:36
PMEmail Poster
Top
emagi
Публикувано на: 05-05-2022, 11:39
Quote Post



Име:
Група: Потребител
Ранг: Редовен член

Мнения: 565
Регистриран на: 12.03.07



QUOTE (thrawn @ 05-05-2022, 11:30)
icon_smile.gif асинхронност в рамките на една нишка се постига ако в нея има "цикъл за обработка на съобщения". Текущия код се обработва в текущата итерация а асинхронноя се посъавя на опашка за обработка при някоя следваща итерация. Така получаваш неблокиращо поведение. PHP не предлага такава архитектура.

Това, че PHP не поддържа неща вида на Promise ми е ясно. Начина, по който аз съм написал кода и сходен с това, че това извикване на втория request, е все едно да бъде записан в QUEUE, и изпълнен в следващата итерация, както писа ти.
Сега да се върнем към кода. Някой да имам идеи, защо се получава този феномен?
PMEmail Poster
Top
emagi
Публикувано на: 05-05-2022, 11:42
Quote Post



Име:
Група: Потребител
Ранг: Редовен член

Мнения: 565
Регистриран на: 12.03.07



QUOTE (thrawn @ 05-05-2022, 11:30)
icon_smile.gif асинхронност в рамките на една нишка се постига ако в нея има "цикъл за обработка на съобщения". Текущия код се обработва в текущата итерация а асинхронноя се поставя на опашка за обработка при някоя следваща итерация. Така получаваш неблокиращо поведение. PHP не предлага такава архитектура.

Това което правиш си е най-обикновено блокиращо извикване.

Нищо не се блокира, докато не извикам fgets(). Направя ли го, означава че ме интересува резултата, което ми и забавя duration на заявката. Разликата е от порядъка на 50 ms
Tочто това съм и описал в поста. Само че в случая на сървъра, без fgets() не се извършва call срещу API
PMEmail Poster
Top
emagi
Публикувано на: 05-05-2022, 11:44
Quote Post



Име:
Група: Потребител
Ранг: Редовен член

Мнения: 565
Регистриран на: 12.03.07



При дебъг чрез POSTMAN при следният код:
CODE

......
.......
........
http_response_code(200);
$this->saveData.... // send request to API

се получава следното: получавам статуса 200, и след това влизам в breakpoint-а и респективно в debug режим

Това мнение е било редактирано от emagi на 05-05-2022, 11:47
PMEmail Poster
Top
thrawn
Публикувано на: 05-05-2022, 11:45
Quote Post



Име:
Група: Потребител
Ранг: Почетен член

Мнения: 3341
Регистриран на: 17.01.17



Не е асинхронен бе човек. Отварянето на сокет е блокираща операция, писането в него също.
Целия ти код блокира докато комуникацията не приключи.

Какво не р на ред на сървъра си пише в логовете му (error). Защото в последните години извеждането на грешки и предупреждения в php е спряно по-подразбиране (в дев среда е редно да си ги включиш де).

Има вариант да затваряш сокета преди да се изпратят реално данните, затова иавиквай fflush преди да го затвориш.

---едит---
Горния код би имал смисъл само ако ръчно изпращаш буфера на php интерпретатора. В противен случай ще се изпрати чак след приключване на скрипта (или при препълване).

Това мнение е било редактирано от thrawn на 05-05-2022, 11:53
PMEmail Poster
Top
emagi
Публикувано на: 05-05-2022, 11:52
Quote Post



Име:
Група: Потребител
Ранг: Редовен член

Мнения: 565
Регистриран на: 12.03.07



QUOTE (thrawn @ 05-05-2022, 11:45)
Не е асинхронен бе човек. Отварянето на сокет е блокираща операция, писането в него също.
Целия ти код блокира докато комуникацията не приключи.

Какво не р на ред на сървъра си пише в логовете му (error). Защото в последните години извеждането на грешки и предупреждения в php е спряно по-подразбиране (в дев среда е редно да си ги включиш де).

Е естествено, че самото създаване на request-a, до неговото изпращане в този случай чрез fsockopen е част от самата логига. Имам в предвид , че изпълнението на втората логична операция, тоест записването на мета-данните в база-данни е процес....
Както и да е
PMEmail Poster
Top
rvc
Публикувано на: 05-05-2022, 12:05
Quote Post



Име:
Група: Потребител
Ранг: Почетен член

Мнения: 2612
Регистриран на: 13.05.11



защо не използваш UDP сокети?
PMEmail PosterUsers Website
Top
1 потребители преглеждат тази тема в момента (1 гости, 0 анонимни потребители)
Потребители, преглеждащи темата в момента:

Topic Options Reply to this topicStart new topicStart Poll

 


Copyright © 2003-2019 | BG Development | All Rights Reserved
RSS 2.0