Czy w PHP jest sposób wykonywania asynchronicznych wywołań HTTP? Nie dbam o odpowiedź, chcę po prostu zrobić coś takiego file_get_contents()
, ale nie czekam na zakończenie żądania przed wykonaniem reszty mojego kodu. Byłoby to bardzo przydatne do wywoływania „zdarzeń” w mojej aplikacji lub uruchamiania długich procesów.
Jakieś pomysły?
php
http
asynchronous
Brent
źródło
źródło
Odpowiedzi:
Odpowiedź, którą wcześniej zaakceptowałem, nie zadziałała. Nadal czekał na odpowiedzi. To jednak działa, wzięte z Jak wykonać asynchroniczne żądanie GET w PHP?
źródło
curl_post_async
i zdobywać nawet głosy poparcia ...Jeśli kontrolujesz cel, który chcesz wywołać asynchronicznie (np. Własny „longtask.php”), możesz zamknąć połączenie z tego końca, a oba skrypty będą działały równolegle. Działa to tak:
Próbowałem tego i działa dobrze. Ale quick.php nie będzie wiedział nic o tym, jak radzi sobie longtask.php, chyba że stworzysz jakieś środki komunikacji między procesami.
Wypróbuj ten kod w longtask.php, zanim zrobisz cokolwiek innego. Zamknie połączenie, ale nadal będzie działać (i pomija wszelkie dane wyjściowe):
Kod jest kopiowany z notatek przesłanych przez użytkownika instrukcji PHP i nieco ulepszony.
źródło
while(true);
po kodzie. Strona się zawiesi, co oznacza, że nadal działa na pierwszym planie.Możesz zrobić oszustwo, używając exec (), aby wywołać coś, co może wykonywać żądania HTTP, na przykład
wget
, ale musisz przekierować gdzieś wszystkie dane wyjściowe z programu, takie jak plik lub / dev / null, w przeciwnym razie proces PHP będzie czekać na to wyjście .Jeśli chcesz całkowicie oddzielić proces od wątku apache, spróbuj czegoś takiego (nie jestem tego pewien, ale mam nadzieję, że masz pomysł):
To nie jest fajna sprawa i prawdopodobnie będziesz potrzebować czegoś takiego jak zadanie cron wywołujące skrypt pulsu, który odpytuje rzeczywistą kolejkę zdarzeń bazy danych w celu wykonania prawdziwych zdarzeń asynchronicznych.
źródło
exec("curl $url > /dev/null 2>&1 &");
jest jednym z najszybszych rozwiązań. Jest niesamowicie szybszy (1,9 na 100 iteracji) niżpost_without_wait()
funkcja (14,8 s) w „zaakceptowanej” odpowiedzi powyżej. I to jest jedno-liniowiec ...Od 2018 roku Guzzle stał się standardową biblioteką defacto dla żądań HTTP, używaną w kilku nowoczesnych frameworkach. Jest napisany w czystym PHP i nie wymaga instalowania żadnych niestandardowych rozszerzeń.
Może bardzo ładnie wykonywać asynchroniczne połączenia HTTP, a nawet łączyć je, np. Gdy trzeba wykonać 100 połączeń HTTP, ale nie chce się uruchamiać więcej niż 5 na raz.
Przykład równoczesnego żądania
Zobacz http://docs.guzzlephp.org/en/stable/quickstart.html#concurrent-requests
źródło
źródło
&
koniec?Możesz użyć tej biblioteki: https://github.com/stil/curl-easy
Jest to więc dość proste:
Poniżej możesz zobaczyć wyjście konsoli z powyższego przykładu. Wyświetli prosty zegar na żywo wskazujący, ile czasu trwa żądanie:
źródło
Fałszywa aborcja przy użyciu
CURL
ustawienia niskiegoCURLOPT_TIMEOUT_MS
ustawione
ignore_user_abort(true)
na kontynuowanie przetwarzania po zamknięciu połączenia.Dzięki tej metodzie nie trzeba wdrażać obsługi połączeń za pośrednictwem nagłówków i buforów zbyt zależnych od wersji systemu operacyjnego, przeglądarki i PHP
Proces główny
Proces w tle
NB
Zasoby
przekroczenie limitu czasu poniżej 1000 ms zawsze kończy się niepowodzeniem?
http://www.php.net/manual/en/function.curl-setopt.php#104597
http://php.net/manual/en/features.connection-handling.php
źródło
pozwól, że pokażę ci moją drogę
wymaga zainstalowania nodejs na serwerze
(mój serwer wysyła 1000 próśb o pobranie https zajmuje tylko 2 sekundy)
url.php:
urlscript.js>
źródło
Rozszerzenie swoole. https://github.com/matyhtf/swoole Struktura asynchroniczna i współbieżna dla PHP.
źródło
Możesz używać nieblokujących gniazd i jednego z rozszerzeń pecl dla PHP:
Możesz użyć biblioteki, która daje warstwę abstrakcji między twoim kodem a rozszerzeniem pecl: https://github.com/reactphp/event-loop
Możesz także użyć asynchronicznego klienta HTTP opartego na poprzedniej bibliotece: https://github.com/reactphp/http-client
Zobacz inne biblioteki ReactPHP: http://reactphp.org
Ostrożnie z modelem asynchronicznym. Polecam zobaczyć ten film na youtube: http://www.youtube.com/watch?v=MWNcItWuKpI
źródło
źródło
Rozszerzenie zdarzenia
Rozszerzenie zdarzenia jest bardzo odpowiednie. Jest to port biblioteki Libevent, która jest przeznaczona do sterowanych zdarzeniami operacji we / wy, głównie do pracy w sieci.
Napisałem przykładowego klienta HTTP, który pozwala zaplanować szereg żądań HTTP i uruchomić je asynchronicznie.
To jest przykładowa klasa klienta HTTP oparta na rozszerzeniu Event .
Klasa pozwala zaplanować szereg żądań HTTP, a następnie uruchomić je asynchronicznie.
http-client.php
test.php
To jest przykładowy skrypt po stronie serwera.
Stosowanie
Przykładowe dane wyjściowe
(Przycięty.)
Uwaga: kod jest przeznaczony do długoterminowego przetwarzania w interfejsie CLI SAPI .
W przypadku protokołów niestandardowych rozważ użycie interfejsu API niskiego poziomu, tj. Zdarzeń bufora , buforów . Do komunikacji SSL / TLS polecam interfejs API niskiego poziomu w połączeniu z kontekstem ssl zdarzenia . Przykłady:
Chociaż API HTTP Libevent jest proste, nie jest tak elastyczne jak zdarzenia buforujące. Na przykład interfejs API HTTP obecnie nie obsługuje niestandardowych metod HTTP. Możliwe jest jednak wdrożenie praktycznie dowolnego protokołu przy użyciu niskopoziomowego interfejsu API.
Rozszerzenie Ev
Napisałem również próbkę innego klienta HTTP używającego rozszerzenia Ev z gniazdami w trybie nieblokującym . Kod jest nieco bardziej szczegółowy niż próbka oparta na zdarzeniu, ponieważ Ev jest pętlą zdarzeń ogólnego przeznaczenia. Nie zapewnia funkcji specyficznych dla sieci, ale jest
EvIo
obserwator może w szczególności nasłuchiwać deskryptora pliku zawartego w zasobie gniazda.To jest przykładowy klient HTTP oparty na rozszerzeniu Ev .
Rozszerzenie Ev implementuje prostą, ale potężną pętlę zdarzeń ogólnego przeznaczenia. Nie zapewnia obserwatorów specyficznych dla sieci, ale jego obserwator we / wy może być używany do asynchronicznego przetwarzania gniazd .
Poniższy kod pokazuje, jak można zaplanować żądania HTTP do przetwarzania równoległego.
http-client.php
Testowanie
Załóżmy, że
http://my-host.local/test.php
skrypt wypisuje zrzut$_GET
:Następnie dane wyjściowe
php http-client.php
polecenia będą podobne do następujących:(przycięte)
Uwaga, w PHP 5 gniazd rozszerzeń może ostrzeżenia dla zalogować
EINPROGRESS
,EAGAIN
iEWOULDBLOCK
errno
wartości. Można wyłączyć dzienniki za pomocąDotyczące „reszty” Kodeksu
Kod, który ma działać równolegle z żądaniami sieci, może zostać wykonany na przykład w ramach wywołania zwrotnego timera zdarzeń lub bezczynnego obserwatora Eva . Możesz łatwo to rozgryźć, oglądając próbki wspomniane powyżej. W przeciwnym razie dodam kolejny przykład :)
źródło
Oto działający przykład, po prostu uruchom go i otwórz storage.txt, aby sprawdzić magiczny wynik
źródło
Oto moja własna funkcja PHP, gdy wykonuję POST pod konkretnym adresem URL dowolnej strony .... Przykład: *** użycie mojej funkcji ...
źródło
Klient HTTP ReactPHP asynchroniczny
https://github.com/shuchkin/react-http-client
Zainstaluj przez Composer
Asynchroniczny HTTP GET
Uruchom php w trybie CLI
źródło
Uważam ten pakiet za bardzo użyteczny i bardzo prosty: https://github.com/amphp/parallel-functions
Załaduje wszystkie 3 adresy URL równolegle. Możesz również użyć metod instancji klasy w zamknięciu.
Na przykład używam rozszerzenia Laravel opartego na tym pakiecie https://github.com/spatie/laravel-collection-macros#parallelmap
Oto mój kod:
Ładuje wszystkie potrzebne dane w 10 równoległych wątkach i zamiast 50 sekund bez asynchronizacji zakończyło się w zaledwie 8 sekund.
źródło
Symfony HttpClient jest asynchroniczny https://symfony.com/doc/current/components/http_client.html .
Na przykład możesz
źródło
Limit czasu można ustawić w milisekundach, patrz „CURLOPT_CONNECTTIMEOUT_MS” w http://www.php.net/manual/en/function.curl-setopt
źródło