"Je kan met alle ziel en zaligheid ergens aan werken, maar soms is de uitkomst een zaal vol zieligheid." - Ariën
Vraag
Alle reacties
Als dat uitgeschakeld is, zal het proces inderdaad eindeloos open blijven. Het enige dat nog kan gebeuren is dat een tussenliggende firewall het na een tijdje wel gezegend vindt en de connectie verbreekt. Beiden kanten zullen dan verbaast opkijken.
Maar waarom niet gewoon even testen? Overigens zou je er ook een self-destruct script omheen kunnen fantaseren, dat de eigen PID killed als het te lang open staat.
curl has two options: --connect-timeout and --max-time.
[ Voor 13% gewijzigd door Room42 op 05-06-2019 16:17 ]
Koop al mijn ads!
"Je kan met alle ziel en zaligheid ergens aan werken, maar soms is de uitkomst een zaal vol zieligheid." - Ariën
#define DEFAULT_CONNECT_TIMEOUT 300000 /* milliseconds == five minutes */
Zodra de verbinding verbroken is, als het goed is.AW_Bos schreef op woensdag 5 juni 2019 @ 16:19:
Ik zal eens kijken, maar heb je ook een idee wanneer die instances dan verdwijnen?
Koop al mijn ads!
Wat je zou kunnen doen is het script zijn eigen PID in een temp file laten schrijven met als filename de timestamp waarop het script is gestart. Als het succesvol afsluit, dan verwijdert het script zijn eigen file weer.
Dan kun je een aparte cronjob starten welke kijkt of er scripts overblijven welke X-tijd oud zijn en die dan adhv het PID killen.
Je zou dit zelf eenvoudig kunnen testen door een "server" op te tuigen welke een sleep doet voordat hij de daadwerkelijke data teruggeeft. En kijken hoe het originele PHP script reageert.
[ Voor 17% gewijzigd door Matis op 05-06-2019 16:39 ]
If money talks then I'm a mime
If time is money then I'm out of time
Even buiten het curl / php verhaal om. Vanuit een cron-job start je gewoon een proces. Dat proces stopt pas als het besluit te stoppen, of jij het afschiet. Daarin is PHP niet anders dan een eigen executable, bash script, etc.AW_Bos schreef op woensdag 5 juni 2019 @ 16:10:
Dat wordt mij niet duidelijk. Blijven de PHP-instances dan open staan, of verdwijnen die na korte of langere tijd?
De vraag is hier dus vooral waarom die default curl timeout niet lijkt te werken.
https://niels.nu
Klopt, je zou eventueel met run-one (of een van z'n broertjes) kunnen forceren dat je maar 1 script tegelijkertijd draait.Hydra schreef op woensdag 5 juni 2019 @ 16:41:
Even buiten het curl / php verhaal om. Vanuit een cron-job start je gewoon een proces. Dat proces stopt pas als het besluit te stoppen, of jij het afschiet. Daarin is PHP niet anders dan een eigen executable, bash script, etc.
De timeout wordt pas gevuurd als er na X-tijd geen response van de server komt, maar mogelijk wordt er wel een header teruggegeven maar geen data. Dan is de timeout nutteloos.De vraag is hier dus vooral waarom die default curl timeout niet lijkt te werken.
Gewoon een keer testen met een logger er aan vast of wireshark.
[ Voor 15% gewijzigd door Matis op 05-06-2019 16:50 ]
If money talks then I'm a mime
If time is money then I'm out of time
Die is standaard vijf minuten. En als er dan nog een nieuw script tot stand komt, en weer een nieuwe... :xHydra schreef op woensdag 5 juni 2019 @ 16:41:
[...]
De vraag is hier dus vooral waarom die default curl timeout niet lijkt te werken.
Het punt waarom ik dit vraag is omdat een van mijn servers (vps) opeens out-of-memory raakt in de nacht op een wisselend tijdstip. En ik nu dit script verdenk van een druppel die de emmer op een 'drukke servernode'* laat overlopen. De laatste keer dat de data nog binnenstroomde is ook de datum dat in de nacht de boel out-of-memory raakte.
Gelukkig zijn ze behulpzaam en kijken ze of ik naar een andere node gemigreerd kan worden.
* Aldus mijn hosting.
Anyway:
Via
ps aux | awk '{print $6/1024 " MB\t\t" $11}' | sort -n -rKan je hier ook de tijden bij ophalen wanneer die aangeroepen worden?
[ Voor 20% gewijzigd door AW_Bos op 05-06-2019 17:27 ]
"Je kan met alle ziel en zaligheid ergens aan werken, maar soms is de uitkomst een zaal vol zieligheid." - Ariën
Hoe kun je dan verklaren dat je, met een cURL timeout van 5 minuten, 50 jobs hebt openstaan? In het meest ruige scenario dat je iedere minuut het scrip afvuurt, zou je maximaal 5 openstaande requests / scripts kunnen hebben.
Tenzij, zoals eerder door mij gesuggereerd, er alvast een header komt en de data oneindig lang op zich laat wachten.
If money talks then I'm a mime
If time is money then I'm out of time
Ik vond het ook frappant. Misschien dat die hele timeout niet werkt? Zou wel erg nasty zijnMatis schreef op woensdag 5 juni 2019 @ 17:45:
Ik ga er, gemakshalve, vanuit dat je maar 1 PHP script per keer dat de cronjob draait, start.
Hoe kun je dan verklaren dat je, met een cURL timeout van 5 minuten, 50 jobs hebt openstaan? In het meest ruige scenario dat je iedere minuut het scrip afvuurt, zou je maximaal 5 openstaande requests / scripts kunnen hebben.
Tenzij, zoals eerder door mij gesuggereerd, er alvast een header komt en de data oneindig lang op zich laat wachten.
Ik heb de shitload aan php-processes de nek omgedraaid, en voor het gemak even de server een reboot gegeven, en nu is er aanzienlijk minder geheugen in gebruik.
Maar, het blijft vreemd
Misschien moet ik curl maar eens updaten?
"Je kan met alle ziel en zaligheid ergens aan werken, maar soms is de uitkomst een zaal vol zieligheid." - Ariën
If money talks then I'm a mime
If time is money then I'm out of time
Wil je zeggen dat het ene beter is dan de andere?
"Je kan met alle ziel en zaligheid ergens aan werken, maar soms is de uitkomst een zaal vol zieligheid." - Ariën
Verwijderd
Voor de zekerheid: jouw kant is die waar cron een php-script start (je laatste zin ‘wat er op de server gebeurt’ is wat ambigu, jouw server is de cliënt
Toevoeging: handig design pattern voor interacties met externe systemen Wikipedia: Circuit breaker design pattern (niet praktisch in dit geval, ter learing ende vermeack
[ Voor 45% gewijzigd door Verwijderd op 05-06-2019 18:46 ]
Dat is precies wat run-once doetVerwijderd schreef op woensdag 5 juni 2019 @ 18:34:
Ik zou als lapmiddel een php of bash (wrapper) scriptje schrijven wat er voor zorgt dat je php script niet opnieuw gestart wordt als de oude nog draait. Daarin kun je ook wat debug spul zetten, lsof voor open tcp/ip connecties (zie je meteen de status) bijvoorbeeld.
If money talks then I'm a mime
If time is money then I'm out of time
Vanuit PHP is in ieder geval een stuk eenvoudiger en je hebt er meer controle over. Nadeel is wel dat de versie van curl afhangt van de versie van PHP.AW_Bos schreef op woensdag 5 juni 2019 @ 18:26:
Ik gebruik cURL vanuit PHP,en dus niet via exec.
Wil je zeggen dat het ene beter is dan de andere?
If money talks then I'm a mime
If time is money then I'm out of time
In mijn ervaring werkt de timeout wel. Maar er zijn meerdere potentieel relevante scenario's die voor een lange doorlooptijd kunnen zorgen.AW_Bos schreef op woensdag 5 juni 2019 @ 17:53:
Ik vond het ook frappant. Misschien dat die hele timeout niet werkt? Zou wel erg nasty zijn
- De server reageert niet
Hiervoor is de connect timeout, maar 5 minuten is normaal gesproken veel te lang daarvoor...
- De server accepteert een tcp-verbinding en je http-request maar doet daarna heel lang over het geven van de eerste paar bytes van de response
Dit valt niet onder de connect timeout, maar er zijn wel manieren om hier iets voor te doen.
Een goede grens hangt van de request die je doet. Als je de Tweakers homepage opvraagt is 5 seconde eigenlijk al te lang, maar als je sommige van onze exports opvraagt is een paar minuten wachten tot de server begint met sturen helemaal niet gek.
- De server heeft veel tijd nodig om steeds een beetje data naar je te sturen.
Hiervoor heeft connect timeout geen effect, de algemene timeout wel en zie hieronder voor nog een oplossing.
Al met al hebben wij deze paar flags ingesteld als we bijvoorbeeld prijslijsten van winkels downloaden:
CURLOPT_CONNECTTIMEOUT
Die hebben wij op altijd 10 seconden staan, je kan ook de versie met _MS gebruiken als je preciezer wilt kunnen sturen.
10 seconde is nog best veel, dus dat kan je evt verlagen als je minder coulant wilt zijn.
CURLOPT_TIMEOUT
Deze generieke timeout geldt voor de totale doorlooptijd van het proces.
Die hebben wij voor de meeste situaties op oneindig, maar voor de prijslijsten op 15 minuten. Ook hier is een _MS versie van.
CURLOPT_LOW_SPEED_LIMIT en CURLOPT_LOW_SPEED_TIME
Deze twee samen zorgen ervoor dat curl kan stoppen als het "te langzaam gaat".
Ook die staat bij ons meestal op oneindig, maar voor de prijslijsten hanteren we een minimum van 100 bytes per seconde (de limit krijgt dus als waarde 100) voor een periode van 4 minuten (en time dus 60*4).
Anders gezegd; als er langer dan 4 minuten (bijna) niks binnenkomt kappen we de boel af.
Alle instellingen zijn overigens gebaseerd op observaties en hier en daar wat 'gut feeling', de precieze grenzen zijn daardoor niet per se met exacte wetenschap onderbouwd
Daarnaast hebben wij ook nog een limiet ingesteld voor de totale grootte van de download. Dat komt voort uit het feit dat we wel eens een winkel hebben gehad die een oneindige loop in hun export-code hadden, waardoor wij effectief een oneindige file met foutmeldingen kregen... Na 32GB aan foutmelding-regels hield dat op omdat de disk vol zat
Helaas heeft curl geen hele makkelijke manier om dat te doen, je moet dat 'hacken' (voor zover wij weten) met CURLOPT_WRITEFUNCTION. En het werkt helaas niet samen met CURLOPT_RETURNTRANSFER.
Als je Guzzle gebruikt, dan is dat laatste trouwens makkelijker doordat je dan de DroppingStream kan gebruiken bij je Sink.
Argh!AW_Bos schreef op woensdag 5 juni 2019 @ 18:26:
Ik gebruik cURL vanuit PHP,en dus niet via exec.
Verklaart de rare spelling
[ Voor 8% gewijzigd door Hydra op 06-06-2019 09:52 ]
https://niels.nu
De opstapeling van processen kwam voort doordat een server niet reageerde op een API-request van mijn kant. Blijkbaar sta ik (onterecht?) op een blacklist en blijft die verbinding maar open staan.
Ik heb inmiddels die server via een proxy-script van een vriend benaderd. En dus voor de zekerheid een timeout ingesteld. 700 MB aan opgestapelde php-processen slaan gewoon nergens op. Misschien is het nog mooier om met een wrapper te werken die de cron niet uitvoert als hij nog loopt.
Ik ga ook even de link van @Verwijderd even bekijken. Altijd interessant
"Je kan met alle ziel en zaligheid ergens aan werken, maar soms is de uitkomst een zaal vol zieligheid." - Ariën
Verwijderd
Ik vermoed van niet. Of die server zou misschien door eigen problemen te lang op een request gewacht hebben waarna ik opnieuw een request maakte. Of toevallig gelijktijdig een request te samen met mijn verstoringen-cronjob iemand die een handmatig aangeroepen script die de reis-mogelijkheden ophaalt.Verwijderd schreef op zaterdag 8 juni 2019 @ 17:31:
@AW_Bos misschien ben je op een blacklist gekomen omdat je teveel gelijktijdige verbindingen had
De NS mag het zeggen
Een script wat vier jaar lang elke 5 minuten bij hen op nette wijze de verstoringen ophaalt moet toch geen probleem vormen
Gelukkig is het een verouderde API die toch over een maand of wat offline gaat. Maar het feit dat anderen wel die server kunnen bereiken lijkt me niet te duiden op een uitfasering van die API-server.
[ Voor 33% gewijzigd door AW_Bos op 08-06-2019 18:14 ]
"Je kan met alle ziel en zaligheid ergens aan werken, maar soms is de uitkomst een zaal vol zieligheid." - Ariën
No trees were harmed in creating this message. However, a large number of electrons were terribly inconvenienced.
Ik heb van iemand (via DM) begrepen dat ze nu verplicht gzip verwachten....Verwijderd schreef op zaterdag 8 juni 2019 @ 18:25:
Servers van de NS moeten inderdaad wel wat kunnen hebben
Wel apart dat de server anders maar blijft wachten.
Nu maar eens kijken waarom dat bij mij niet aan staat.
Ik vind dit een tricky function. Waarom zou je jouw script als je die via de browser zou oproepen willen laten lopen?
[ Voor 32% gewijzigd door AW_Bos op 08-06-2019 19:25 ]
"Je kan met alle ziel en zaligheid ergens aan werken, maar soms is de uitkomst een zaal vol zieligheid." - Ariën
Die timeout van PHP zelf is niet geldig bij CLI, hij zal dus blijven doorlopen, tenzij je iets anders doet met die CURL, return en/of exit aanroept.Room42 schreef op woensdag 5 juni 2019 @ 16:15:
Geen timeout meegeven is iets dat je bewust moet doen. Standaard staat er wel een timeout ingesteld in de vorm van een max_execution_time.
Als dat uitgeschakeld is, zal het proces inderdaad eindeloos open blijven. Het enige dat nog kan gebeuren is dat een tussenliggende firewall het na een tijdje wel gezegend vindt en de connectie verbreekt. Beiden kanten zullen dan verbaast opkijken.
Maar waarom niet gewoon even testen? Overigens zou je er ook een self-destruct script omheen kunnen fantaseren, dat de eigen PID killed als het te lang open staat.
edit:Oh, cURL kan het zelf ook: https://unix.stackexchang...ave-a-timeout/94612#94612
[...]
Als je niet wil dat het script eindigt voordat het ook echt klaar isAW_Bos schreef op zaterdag 8 juni 2019 @ 19:24:
[...]
Ik vind dit een tricky function. Waarom zou je jouw script als je die via de browser zou oproepen willen laten lopen?
Dat zal bij requests die alleen maar data uitlezen of requests die idempotent zijn niet zo veel uitmaken, maar als je een request hebt die veel data muteert (en je kan dat niet afvangen met een transactie van je RDBMS ofzo) dan zou dit nog enige zekerheid kunnen bieden dat je script in ieder geval gewoon z'n ding doet. Of eigenlijk; je haalt een stukje risico weg dat het halverwege afgebroken wordt door de http client (en dan blijven er nog een heleboel andere stukjes risico over).
Edit:
Waar haal je dat vandaan? Voor zover ik weet wordt die ook door de CLI SAPI net zo goed ge-enforced. Met enig verschil dat sommige distro's een aparte php.ini hanteren voor CLI waarin die misschien op -1 staat?HollowGamer schreef op zaterdag 8 juni 2019 @ 19:36:
[...]
Die timeout van PHP zelf is niet geldig bij CLI, hij zal dus blijven doorlopen, tenzij je iets anders doet met die CURL, return en/of exit aanroept.
[ Voor 23% gewijzigd door Freeaqingme op 08-06-2019 19:40 ]
No trees were harmed in creating this message. However, a large number of electrons were terribly inconvenienced.
Verwijderd
@AW_Bos als gzip verplicht is, wat kan, zou de proxy van je vriend dat dan gebruiken als jij het niet aan hebt staan?
"Je kan met alle ziel en zaligheid ergens aan werken, maar soms is de uitkomst een zaal vol zieligheid." - Ariën
Van PHP zelf: https://www.php.net/manua...hp#ini.max-execution-timeFreeaqingme schreef op zaterdag 8 juni 2019 @ 19:39:
[...]
Als je niet wil dat het script eindigt voordat het ook echt klaar is![]()
Dat zal bij requests die alleen maar data uitlezen of requests die idempotent zijn niet zo veel uitmaken, maar als je een request hebt die veel data muteert (en je kan dat niet afvangen met een transactie van je RDBMS ofzo) dan zou dit nog enige zekerheid kunnen bieden dat je script in ieder geval gewoon z'n ding doet. Of eigenlijk; je haalt een stukje risico weg dat het halverwege afgebroken wordt door de http client (en dan blijven er nog een heleboel andere stukjes risico over).
Edit:
[...]
Waar haal je dat vandaan? Voor zover ik weet wordt die ook door de CLI SAPI net zo goed ge-enforced. Met enig verschil dat sommige distro's een aparte php.ini hanteren voor CLI waarin die misschien op -1 staat?
Je wilt namelijk niet die timeout bij het uitvoeren van scripts. Dat sommige distro's hier dus wel iets mee doen, is tegenwoordig niet echt handig. Wat als je een framework gebruikt met jobs/tasks als Laravel?
Nog belangrijker dan de standaardwaarde van 0 in de CLI is dit stukje:HollowGamer schreef op zaterdag 8 juni 2019 @ 20:00:
[...]
Van PHP zelf: https://www.php.net/manua...hp#ini.max-execution-time
Je wilt namelijk niet die timeout bij het uitvoeren van scripts. Dat sommige distro's hier dus wel iets mee doen, is tegenwoordig niet echt handig. Wat als je een framework gebruikt met jobs/tasks als Laravel?
The maximum execution time is not affected by system calls, stream operations etc.
I stand corrected. Dacht dat dit een ini-dingetje was, maar blijkt dat het voor de CLI SAPI weldegelijk hardcoded is.
Tjah, dat wil ik in een HTTP omgeving ook nietHollowGamer schreef op zaterdag 8 juni 2019 @ 20:00:
Je wilt namelijk niet die timeout bij het uitvoeren van scripts. Dat sommige distro's hier dus wel iets mee doen, is tegenwoordig niet echt handig. Wat als je een framework gebruikt met jobs/tasks als Laravel?
Moet wel zeggen, ik heb een hoop met shared webhosting gedaan, en wat sommige klanten dan denken te kunnen doen is bizar. Ik heb klanten meegemaakt die wat hen betreft 10GiB konden uploaden via HTTP, en dat dan bij wijze van spreken on the fly te transcoden in dezelfde http request.
No trees were harmed in creating this message. However, a large number of electrons were terribly inconvenienced.