Kdyby/Curl – casty vyskyt chyby „Operation timed out after…“
- flipis
- Člen | 12
Ahoj,
pracujem na projekte, kde potrebujem odosielat roznym partnerom cez rozne API nejake data. Tie API su naozaj vsetkeho mozneho druhu, ale v konecnom dosledku ide vsetko vacsinou cez klasicky POST. Pouzivam Kdyby/Curl, no vyskytol sa tam jeden problem – v logoch sa zacali objavovat chyby typu
Kdyby\Curl\FailedRequestException: Operation timed out after 15001 milliseconds with 0 bytes received in /*****/libs/kdyby/curl/src/Kdyby/Curl/CurlSender.php:314
Najskor sa to nestavalo casto (5–6× denne). Pri mnozstve requestov, ktore boli odoslane (± 1000 denne) to bolo zanedbatelne, navyse som to bral tak, ze na strane partnerov moze dojst k obcasnym vypadkom, kedy server neodpoveda atd. Postupne s napajanim dalsich partnerov to vsak narastalo az to zacalo byt uz celkom kriticke ( radovo desiatky timeoutov denne). Skusal som zvysit timeout v RequestOptions, ale nic sa nezmenilo (navyse sa v hlaseni chyby nadalej vyskytuje 15000 ms, takze to vyzera, ako keby to zvysenie timeoutu ani neregistroval). Kazdopadne tie requesty by casovo aj tak nemali presahovat 1–2 sekundy.
To, ze problem bude niekde v Kdyby som zistil, ked som to prepisal cez ciste PHP-ckovske curl (timeouty zmizli), ale nerad by som to tak nechal – predsalen s Kdyby sa pracuje pohodlnejsie :) Mate niekto nejaky napad, v com by to mohlo viaznut?
Editoval flipis (8. 8. 2014 16:56)
- Filip Procházka
- Moderator | 4668
15 vteřin je totiž výchozí timeout, který můžeš snadno změnit na
Curl\Request
nebo na Curl\CurlSender
v $options a pak je ještě connectionTimeout, který jsi nejspíš nezkoušel.
V Kdyby chyba určitě není, to že ti to žádnou chybu nehází s čistým curl nejspíš jenom znamená, že o té chybě jenom nevíš :)
Tyhle chyby musíš totiž odchytávat a když nastanou, tak s nimi nějak pracovat, například tak že request pustíš znova. Nebo ho dáš na konec fronty a pustíš ho znova za hodinu. Třeba.
- flipis
- Člen | 12
@FilipProcházka
15 vteřin je totiž výchozí timeout, který můžeš snadno změnit na
Curl\Request
nebo naCurl\CurlSender
v $options a pak je ještě connectionTimeout, který jsi nejspíš nezkoušel.
Mozem to este vyskusat, ale ako vravim, tych 15 sekund bohato postacuje…chcel som to vyskusat len cisto ako poslednu moznost, ked som bol uz zufaly :)
V Kdyby chyba určitě není, to že ti to žádnou chybu nehází s čistým curl nejspíš jenom znamená, že o té chybě jenom nevíš :)
So sklopenymi usami priznavam, ze tie chyby naozaj neodchytavam :) (chabym pokusom o ospravedlnenie moze byt, ze som to naozaj pisal len tak narychlo, lebo som chcel vyskusat inu alternativu). Ale to, ze tie chyby nenastavaju viem podla toho, ze odchytavam a ukladam responses, ktore sa vracaju naspat. A tie proste chodia bez problemov. Myslim, ze keby tie timeouty nastavali aj tam, tak ta odpoved nepride ci?
@Majkl578
Tie API, kde pouzivam Kdyby a kde to vypadava su vacsinou klasicke POST
requesty. Konkretne kod toho, u ktoreho sa to stavalo najcastejsie vyzeral
uplne primitivne:
$data = array(
...
);
$request = new \Kdyby\Curl\Request(self::PUSH_URL);
$response = $request->post($data);
Tiez som si myslel, ze to nastava na strane prijemcu, ale stava sa to u vsetkych (niekde viac, inde menej casto), navyse ten u ktoreho sa to stava najcastejsie nema na svojej strane ziadne zaznamy o chybe. Plus teda to s tym nahradenim za ciste curl, ktore popisujem vyssie.
- Filip Procházka
- Moderator | 4668
Seš si 100% jistej že úplně všechny requesty které jsi za několik dní udělal, prošly naprosto bez problému? Takovouhle sebejistotu bych neměl, ani kdybych měl server na páteřní síti s 10 UPSkama za prdelí :)
Failed request v 99% znamená že chyba byla v tvém počítači nebo v síti – tedy nepovedlo se odeslat a když se povedlo odeslat, tak se nepovedlo spojit s cílovým serverem. Pointa je, že máš request zkusit znovu, protože chyby na síti se prostě stávat můžou.
- flipis
- Člen | 12
Seš si 100% jistej že úplně všechny requesty které jsi za několik dní udělal, prošly naprosto bez problému? Takovouhle sebejistotu bych neměl, ani kdybych měl server na páteřní síti s 10 UPSkama za prdelí :)
Ale jasne ze 100% to nie je :) ale na rozdiel od predchadzajuceho stavu
proste dostavam odpovede od partnerskeho API vo vsetkych pripadoch, ked nieco
odoslem (OK pripustme, ze sa obcas nezachyti samotne odoslanie a tym padom ani
pripadna chyba, ale to je naozaj velmi mala pravdepodobnost).
To nie je o tom, ze kedze nemam osetrene odchytavanie vynimiek, tak teraz vidim
iba tie co presli a myslim si, ze vsetko je OK. Ten pocet odoslanych requestov
sa nezmenil (samozrejme ±, lebo to nie su exaktne cisla), naproti tomu pocet
prijatych responses rapidne stupol.
Failed request v 99% znamená že chyba byla v tvém počítači nebo v síti – tedy nepovedlo se odeslat a když se povedlo odeslat, tak se nepovedlo spojit s cílovým serverem. Pointa je, že máš request zkusit znovu, protože chyby na síti se prostě stávat můžou.
Tu som nechcel zachadzat az do detailov, ale pokusim sa to objasnit. Problem je prave v tom, ze neviem, kde ta chyba nastala a ci tie data pri tom timeoute k partnerovi presli alebo nie. Pretoze ked som si to porovnaval s udajmi od druhej strany, tak nasli sa take, ktore presli, ale takisto take, ktore som mal iba u seba a u partnera neboli. Ak by som kazdy chybny request poslal znova, partner mi zacne frflat, ze dostava duplicitne data. Preto to momentalne riesim tak, ze chybne requesty ignorujem (pri nizkom percente je to prijatelne), maximalne to potom nejak zosumarizujeme, porovname a chybajuce data dodatocne preposlem (povedzme raz za mesiac).
Este aby nevzniklo nedorozumenie – neznazim sa hadzat vinu na Kdyby :) Ani netvrdim, ze to je chyba…skor sa snazim prist na to, ci Kdyby nahodou nema oproti klasickemu curl nejake defaultne nastavenia alebo poziadavky, alebo proste nieco, co by tomu mohlo vadit.
- Filip Procházka
- Moderator | 4668
Já si pořád myslím, že chybovost je stejná, jenom o tom nevíš.
A s partnery si předělejte api, abys mohl jednu informaci poslat dvakrát. Snad není takový problém kontrolovat unikátnost.
- flipis
- Člen | 12
S tymi partnermi je to tazke, s niektorymi sa da, s inymi nie. To je tazko vysvetlovat :)
K veci:
Data odosielam na 2 miesta – k sebe do lokalnej DB a k partnerovi cez API.
VZDY to ide najskor do DB a teda ked aj request na API zlyha, v DB je ulozeny
zaznam s odoslanymi datami. Ked nezlyha a vrati mi odpoved, tak si ju dodatocne
k tym prislusnym datam v DB ulozim. Takze aj keby som nevidel chyby v logoch
kvoli tomu ze som ich neodchytaval, videl by som zaznamy v DB, ktore nemaju
odpoved.
To odchytavanie chyb som tam doplnil tiez. Ak nastane v curl nejaka chyba, vyvola sa vynimka a ta by mala byt zachytena v logoch. Cize to teraz zjednodusene vyzera nejak takto:
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, self::PUSH_URL);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
$result = curl_exec($curl);
$error = curl_error($curl);
if(!empty($error))
{
throw new \Exception(curl_error($curl), curl_errno($curl));
}
curl_close($curl);
Testujem to iba par hodin, ale vynimky sa zatial neobjavili. Ak robim niekde chybu, oprav ma.
- Filip Procházka
- Moderator | 4668
if (($errorCode = curl_errno($curl)) !== CURL_OK) {
throw new \Exception(curl_error($curl), $errorCode);
}
if (($httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE)) != 200) {
throw new \Exception("Communication error", $httpCode);
}
- flipis
- Člen | 12
Tak som to nahodil vcera rano. Do dnesneho rana sa odchytila jedina vynimka, aj to az v tej druhej kontrole – vratila sa 504-ka Bad Gateway, o tej ale viem, ze raz za cas tam nastane. Inak nic.
Tak a teraz uz fakt neviem :| Nejake dalsie napady? Neverim, ze som prvy a jediny, ktory sa s tymto stretol :)