|
[ Faun @ 05.10.2010. 11:40 ] @
| Potrebno je da napravim funkciju koja će da se izvršava na serveru u pozadini, a da ostatak sajta normalno funkcioniše. Nešto kao niti u Javi. Gledao sam PCNTL proširenje za php, međutim za njega je potrebno ručno kompajlirati php.
Da li je nešto ovako uopšte moguće u php? Nov sam u php, pa me baš iznenadilo da se ovako jednostavna stvar tako teško rešava.
P.S. Funkcija čita podatke iz baze, radi neke proračune, i upisuje u bazu. |
[ vatri @ 05.10.2010. 11:57 ] @
Tebi vjerovatno treba AJAX ;)
[ ksrele @ 05.10.2010. 12:08 ] @
Pojasni malo vise sta ti konkretno treba?
Zasto jednostavno ne resis taj problem tako da kada god ti dodje neki korisnik na sajt da on pokrene tu funkciju koja nesto odradi?
Ukoliko ti treba da ti se funkcija odradi odredjeni broj puta u odredjeno vreme bez obzira da li neko posacuje sajt ili ne onda ti treba Google: "php cron job".
Iskreno, ja ga nikad nisam koristio i ne znam kako se koristi ali na svim novijim hosting serverima imas u njihovom cPanelu ugradjenu podrsku sa Cron, ako sam ja dobro primetio.
[ Nemanja Avramović @ 05.10.2010. 15:13 ] @
Ajax ti može pozivati PHP fajl u pozadini, a taj PHP će raditi šta treba, ali to samo radi kad je posetilac na strani koja poziva ajax.
Kao što ksrele reče, ako ti treba nešto da se obavlja u određenim vremenskim intervalima, rešenje je cron job. Imaš ovde uputstvo za cPanel.
[ Faun @ 05.10.2010. 17:17 ] @
Hvala svima na ovako brzim ogdovorima.
Da malo konkretizujem problem. Pravim modul za Drupal koji će da omogu peni aukcijsku prodaju (penny auctions), nešto po uzoru na swoopo.com. Ovo pitanje je vezano za bid butlers (agente prodaje, kako ih ja zovem) koji automatski postavljaju ponude. Svaki korisnik može da aktivira neki i on će se izvršavati nezavisno od toga da li je korisnik ulogovan. Prema tome ne može preko AJAX-a da se realizuje.
Što se tiče cron-a tu je opet problem što se to neće izvršavati u jednakim vremenskim intervalima, već će morati konstantno da se izvršava. Moja ideja je da se kreira beskonačna petlja koja će spavati po 1s i onda proveravati da li ima potrebe da postavi neku ponudu. Ako ima potrebe, da odradi posao i onda opet na spavanje.
Imam osećaj kao da mi neki osnovni koncept tu izmiče, i da ne razmišljam baš na najbolji način. Dakle, rad u pozadini nije sa aspekta korisnika, već sa aspekta ostatka sajta koji treba da nastavi da funkcioniše normalno kao i da ne postoje ovi agenti prodaje.
[ batika @ 05.10.2010. 17:32 ] @
Ako sam dobro razumeo sta ti treba evo ti moja vizija resenja:
1. u bazi cuvaj statuse za korisnike koji su se prijavili za automatsko "bidovanje"
2. Napravis skript koji proverava te statuse i radi sta vec treba da radi.
3. U cron tabu podesis da se taj skript izvrsava na svakih 5 sekundi
Ovo sve pije vodu ako sam dobro skontao sta hoces da postignes...
pozdrav
[ Faun @ 05.10.2010. 17:52 ] @
Zar nije najmanja jedinica za cron 1 minut? Ne znam kako da podesim da mi se cron izvrsava ispod toga.
[ dakipro @ 05.10.2010. 17:55 ] @
A jel tebi treba da se skripta uvek konstantno izvrsava ili samo kada se pojavi nova ponuda? Da li mozes odmah nakon postavljanja ponude da pozoves odmah sve bid butlerse za tu ponudu i onda oni rade to sto treba da rade (biduju ili salju mail ili sta vec)? Mislim da tako limundov "agent prodaje" ili kako ga vec zovu radi, inicira se odmah nakon postavljanja nove ponude (posle svakog bida)
[ Faun @ 05.10.2010. 18:18 ] @
Skripta se izvšava samo za one proizvode kod kojih je vreme do kraja palo ispod 10s. Ona jedanput iskenira sve "agente prodaje" i proizvode vezane za njih i to smesti u jednu promenljivu kako ne bih svaki put slao upit ka bazi. Ukoliko je najmanje vreme do kraja neke aukcije recimo 5 min, onda će skripta da spava narednih 4 min 50s; sem ukoliko neko ne kreira neki novi proizvod, čime se pokreće ponovo skeniranje (postoji mogućnost da taj proizvod ima manje od 5 min do kraja) ili ukoliko neko ne kreira novog "agenta prodaje" (postoji mogućnost da taj agent bude vezan za neki proizvod koji ima manje od 5 min).
[ Goran Rakić @ 05.10.2010. 18:23 ] @
Ja bih ovo rešio sa dva procesa, jedan koji spava u beskonačnoj petlji, i drugi koji se izvršava sa veb stranice (pristup php skriptu) koji sa prvim razmenjuje podatke. Zavisno od opterećenja i robustnosti koju planiraš možeš da između postaviš i jedan message queue sistem, koga će veb stranica da pinguje kada se pojavi nova aukcija ili postavi novi robot, a koji će da isporuči to ovom uspavanom iz pozadine.
Ne vidim razlog da pokrećeš po jedan proces za svakog korisničkog agenta/aukciju, jedan proces je sasvim dovoljan, eventualno ako ti je lakše da tako dizajniraš sistem, jedna nit po aukciji i svakako odvojena nit za komunikaciju sa PHP skriptom na veb stranici ili sa MQ sistemom.
[ Faun @ 05.10.2010. 18:39 ] @
To, to je pravo rešenje :). U početku sam i imao ideju da za svaku aukciju kreiram zasebnu nit, ali sam na kraju sve smestio u jednu funkciju. Međutim, kao što rekoh, nov sam u php-u i ne znam kako funkcioniše to sa nitima ovde i MQ sistemom. Konkretno, ne znam kako da probudim taj proces koji spava. Je l' imaš možde niki link gde mogu to opširnije da pogledam. Recimo, gledao sam za PCNTL proširenje za php, i to je to što meni treba, ali je potrebno ručno kompajlirati php.
[ Goran Rakić @ 05.10.2010. 18:57 ] @
Ne razumem, kako to misliš da probudiš nit koja spava?
[ agvozden @ 05.10.2010. 18:58 ] @
Ja bih isao preko krona za ovo.
Treba ti neka tabela (txt fajl ili sta god) gde ces upisivati zadnju akciju koja se pozvala iz krona. Svaka akcija se upisuje i ispisuje prilikom zavrsenja posla. Akcije koje se jave u medjuvremenu kontaktiraju taj fajl i ukidaju se ukoliko ima aktivnog procesa.
Ovde treba viditi racuna o tome da se skript ne zaglupi - to znaci da treba postojati interval na koji ce upisivati status u ovu datoteku. Ukoliko nova akcija vidi da je skript aktivan dize paniku - ubija proces, obavestava mejlom, ili sta god.
Dakle, slep ali sa jednim okom otvorenim ;)
[ Faun @ 05.10.2010. 19:29 ] @
Citat: Goran Rakić: Ne razumem, kako to misliš da probudiš nit koja spava?
Recimo, imam
Code (php):
function neka_funkcija (){
// radi nesto
sleep(50);
}
Međutim, ja poželim da prekinim to spavanje i da pozovem funkciju posle 10s. Da li je to moguće?
I mnogo važnija stvar, ja ne znam kako da pokrenem recimo dve niti da mi rade paralelno. Tražio sam po netu i ništa nisam našao sem PCNTL-a. Znam da je to neka osnova, ali 
[ vatri @ 05.10.2010. 20:31 ] @
Ja citam vec par puta poruke i ne kontam kakve procese spominjete u PHP-u :) ali nema veze...
Zar ne mozes to rijesiti nekako ovako:
Code (php):
<?php
// negdje na samom pocetku koda (recimo index.php)
if( provjeri_uslov() )
{
akcija();
}
//....
//... nastavak index.php
?>
Funkcija provjeri_uslov() bi pogledala u neku optimizovanu tabelu u MySQL da li treba izvrsiti akciju ili ne.
Sto moras svaku sekundu nesto raditi, ako nema ni jednog korisnika na sajtu?! :)
[ Nikola Poša @ 05.10.2010. 20:44 ] @
Citat: Faun: Recimo, gledao sam za PCNTL proširenje za php, i to je to što meni treba, ali je potrebno ručno kompajlirati php.
PCNTL je verovatno najbolje rešenje za implementaciju multithreading-a u PHP-u. Naravno, postoje i alternative. Ova tri članka ti možda mogu biti od pomoći što se PCNTL-a tiče:
http://www.re-cycledair.com/php-dark-arts-multi-threading-part-1
http://www.re-cycledair.com/php-dark-arts-multi-processing-part-2
http://www.re-cycledair.com/ph...rts-shared-memory-segments-ipc
btw Izgleda da nisam najbolje razumeo ono što ti hoćeš da postigneš, jer ne mogu da skapiram zašto bi igranje sa procesima bilo rešenje za taj tvoj problem.
[ dakipro @ 05.10.2010. 20:45 ] @
@vatri, izgleda da nisi citao par puta dobro sve poruke ;)
Treba da se skripta pozove u recimo 11:59:50 iako tada nema nikog na sajtu, jer je to vreme dogadjaja nekog eventa na sajtu (isticanje aukcije ili sta vec)
[ vatri @ 05.10.2010. 21:32 ] @
Dobro, a u cemu je problem ako se recimo taj "event" dogodi u 12 h, tj. kad prvi korisnik poslije tog vremena dodje na sajt?
U bazi imas vrijeme izvrsavanja eventa i u provjeri_uslov() funkciji jednostavnim query-jem uporedimo NOW() i vrijeme eventa...
[ Faun @ 05.10.2010. 21:57 ] @
Citat: vatri: Dobro, a u cemu je problem ako se recimo taj "event" dogodi u 12 h, tj. kad prvi korisnik poslije tog vremena dodje na sajt?
U bazi imas vrijeme izvrsavanja eventa i u provjeri_uslov() funkciji jednostavnim query-jem uporedimo NOW() i vrijeme eventa...
To bi bilo komplikovanije za implementaciju. Ima dosta AJAX-a, što znači da bih ja u svaku metodu koja se poziva preko ajax-a prvo trebalo da ubacim da mi se izvrše svi "agenti prodaje" koji su bili planirani od poslednjeg pristupanja. A druga stvar, šta ako niko ne poseti sajt danima, a ima gomila "agenata prodaje" koji čekaju (jedan "agent prodaje" može da se izvrši i više puta, verovatno će biti ograničeno na 50, ali treba ostaviti korisniku da odredi taj broj). Nisam siguran, ali meni to izgleda da bi moglo da uspori stvari.
Citat: Nikola Poša: btw Izgleda da nisam najbolje razumeo ono što ti hoćeš da postigneš, jer ne mogu da skapiram zašto bi igranje sa procesima bilo rešenje za taj tvoj problem.
Krenuo sam sa idejom da svaki "agent prodaje" ima svoju nit koja će da postavlja ponude. Pošto sam onda video da ću verovatno imati problema sa multi-threading-om u php, onda sam sve strpao u jednu metodu tako da ručno vodim računa o rangiranju i vremenu izvršavanja svih "agenta prodaje". Tu funkciju ću pozvati preko cron-a.
Sada mi ostaje još da odradim prenošenje poruka. Tj. kako da neka druga funkcija posalje poruku ovoj prvobitnoj da je doslo do promene nekih podatak u bazi kako bi ona učitala sveže podatke.agvozden je predložio Citat: agvozden: Treba ti neka tabela (txt fajl ili sta god) gde ces upisivati zadnju akciju koja se pozvala iz krona. Svaka akcija se upisuje i ispisuje prilikom zavrsenja posla. Akcije koje se jave u medjuvremenu kontaktiraju taj fajl i ukidaju se ukoliko ima aktivnog procesa. ali me zanima da li postoji još neko rešenje, bez upisa u fajl ili bazu, preko neke promenljive.
[ Goran Rakić @ 05.10.2010. 22:54 ] @
Mislim da to što si zamislio može jednostavnije da se implementira.
Počni od problema, a ne od rešenja. Hajde definiši te agente, šta oni rade i kako se odnose prema drugim objektima.
Onaj sleep ne prekidaš (možda može nekim signal handlerom, ali to je nepotrebno). Ako hoćeš aktivno čekanje, onda imaš petlju tipa:
Code (php):while(true) {
// nešto
sleep(1);
}
Sada u samoj petlji možeš da postaviš uslov tipa if(treba_li_da_se_izvrši) ..., i ako ne treba ideš ponovo na čekanje od 1sec.
Još bolje je da imaš neku blokirajuću funkciju, na primer socket_select ili zatražiš neki katanac (engl. lock), koja će ti prekinuti čekanje tek kada se dogodi neki upis na jednom od nadgledanih socketa ili kada oslobodiš katanac iz druge niti/procesa.
Međutim veoma je verovatno da u ovom tvom konkretnom slučaju sve to može jednostavnije.
[ misk0 @ 05.10.2010. 22:55 ] @
Sto se mene tiche tebi treba neki daemon koji ce da monitorishe statuse u pozadini i radi nezavisno od sajta. Mozda bi to mogao i da napises u PHPu, ali mozda je boje imati neki drugi server container za to.
[ Faun @ 06.10.2010. 11:03 ] @
Citat: misk0: Sto se mene tiche tebi treba neki daemon koji ce da monitorishe statuse u pozadini i radi nezavisno od sajta. Mozda bi to mogao i da napises u PHPu, ali mozda je boje imati neki drugi server container za to.
Da, baš to. Samo, ovo je modul za Drupal, pa je potrebno da prosečan korisnik Drupala može lako da ga instalira, bez dodatnih podešavanja.
Citat: Goran Rakić: Mislim da to što si zamislio može jednostavnije da se implementira.
Počni od problema, a ne od rešenja. Hajde definiši te agente, šta oni rade i kako se odnose prema drugim objektima.
Onaj sleep ne prekidaš (možda može nekim signal handlerom, ali to je nepotrebno). Ako hoćeš aktivno čekanje, onda imaš petlju tipa:
Code (php):while(true) {
// nešto
sleep(1);
}
Sada u samoj petlji možeš da postaviš uslov tipa if(treba_li_da_se_izvrši) ..., i ako ne treba ideš ponovo na čekanje od 1sec.
Još bolje je da imaš neku blokirajuću funkciju, na primer socket_select ili zatražiš neki katanac (engl. lock), koja će ti prekinuti čekanje tek kada se dogodi neki upis na jednom od nadgledanih socketa ili kada oslobodiš katanac iz druge niti/procesa.
Međutim veoma je verovatno da u ovom tvom konkretnom slučaju sve to može jednostavnije.
Ni na kraj pameti da primenim sokete. Ekstra ideja, ali koliko sam video i za to je potrebno ručno kompajlirati php. Tako da i to otpada.
Odradiću ga preko one jedne funkcije u cron-u, a katanac ću da čuvam u bazi. I ja imam osećaj da postoji neko elegantnije rešenje, ali mi trenutno ništa ne pada na pamet. Ako nekoga zanima konkretan problem koji rešavam, može da pogleda ovde.
[ Faun @ 07.10.2010. 20:43 ] @
Našao sam odgovor na moje početno pitanje. To je funkcija exec koja ima mogućnost da program poziva u pozadini.
Code (php):
exec("php example.php > log.txt &");
Za izvršavanje u pozadini je zadužen znak na kraju "&" i potrebno je uraditi redirekciju izlaza (u ovom slučaju u fajl log.txt).
Ovo je, doduše, rešenje samo za Linux. Problem ovoga je što će teško koji hosting davati mogućnost za korišćenje ove komande :)
[ vatri @ 08.10.2010. 15:08 ] @
I gdje/kad ces pokretati ovaj kod? Sta ako se server restartuje? :)
[ m_k @ 08.10.2010. 16:19 ] @
Za bilo koju varijantu multithredinga moras ako nista imati instaliranu posebnu extenziju za php, a to prosjecan server sigurno nema.
Ja bih to rijesio preko Cron-a na slijedeci nacin:
- nastimati tu skriptu da se izvrsava svake minute
- e sad planiras da ce se skripta izvrsavati 55 sekundi, i onda prekinuti da bi slijedeci cron poceo
- unutar skripte vrtiti while petlju i svake sekunde pokusavit selektovati aukcije koje se zavrsavaju za manje od 10 sek
- ako ti query vrati neki rezultat odratiti sto imas da odradis na toj aukciji
** Ovdje ces imati ovih 5 sek praznog hoda kad se nista nece desavati. Nikad ne znas koliki ce ti load biti na serveru i koliko ce trebati skripti da se pokrene. Zbog toga mozes ubaciti neki counter koji ce ti garantovati da je aukcija 10 puta "pingana", tj da se odrađeno to sto se mora odraditi 10 puta (Ovo bi moglo uzrokovati da se zadnjih 10 sek aukcije razvuce na 15 sek, a lvaljda tih 5 sek nikome ne znaci previse).
Nadam se da nisam previse konfuzan :)
[ Vladica Savić @ 08.10.2010. 18:16 ] @
Citat: m_k: Za bilo koju varijantu multithredinga moras ako nista imati instaliranu posebnu extenziju za php, a to prosjecan server sigurno nema.....
Izvini, jel mozes malo vise detalja o ovome?
Jer koliko ja znam php nema mogucnost rada sa thread-ovima ili se varam?
[ m_k @ 08.10.2010. 18:43 ] @
Citat: Vladica Savić: Izvini, jel mozes malo vise detalja o ovome?
Jer koliko ja znam php nema mogucnost rada sa thread-ovima ili se varam?
http://kevin.vanzonneveld.net/...article/create_daemons_in_php/
[ Vladica Savić @ 08.10.2010. 20:14 ] @
Pa da, al to nije thread u pravom smislu te reci.
[ Faun @ 08.10.2010. 20:15 ] @
Citat: m_k: Za bilo koju varijantu multithredinga moras ako nista imati instaliranu posebnu extenziju za php, a to prosjecan server sigurno nema.
Ja bih to rijesio preko Cron-a na slijedeci nacin:
- nastimati tu skriptu da se izvrsava svake minute
- e sad planiras da ce se skripta izvrsavati 55 sekundi, i onda prekinuti da bi slijedeci cron poceo
- unutar skripte vrtiti while petlju i svake sekunde pokusavit selektovati aukcije koje se zavrsavaju za manje od 10 sek
- ako ti query vrati neki rezultat odratiti sto imas da odradis na toj aukciji
** Ovdje ces imati ovih 5 sek praznog hoda kad se nista nece desavati. Nikad ne znas koliki ce ti load biti na serveru i koliko ce trebati skripti da se pokrene. Zbog toga mozes ubaciti neki counter koji ce ti garantovati da je aukcija 10 puta "pingana", tj da se odrađeno to sto se mora odraditi 10 puta (Ovo bi moglo uzrokovati da se zadnjih 10 sek aukcije razvuce na 15 sek, a lvaljda tih 5 sek nikome ne znaci previse).
Nadam se da nisam previse konfuzan :)
Nisi konfuzan :). Na kraju će rešenje verovatno i biti takvog tipa. Razmišljam i o tome da se skripta ne prekida na 55 sekunde, već da novi cron pokrene novu skriptu koja će imati uslov da se prekine ukoliko je neka već aktivna. Tj., da mi cron služi samo kao pokretač ukoliko nekim slučajem skripta pukne. Ne znam da li je to moguće, da li će se skripte pokretati u paraleli ili će mi pokretanje druge prekinuti prvu?
Ekstra članak. PCNTL je stvarno ekstra stvar, samo ne znam kada će da ga ubace i u klasične verzije php-a. Kad budem imao vremena baš ću da iskompajliram php sa tom ekstenzijom da vidim kako radi.
[ Faun @ 08.10.2010. 20:22 ] @
Citat: Vladica Savić: Pa da, al to nije thread u pravom smislu te reci.
Je l' može malo pojašnjenje o ovome? Po meni PCNTL zadovoljava sve zahteve neophode za rad sa nitima. E sad, ja opet nisam stručnjak u tome, pa me zanima šta je to što mu fali.
[ m_k @ 08.10.2010. 20:33 ] @
Citat: Faun: Ne znam da li je to moguće, da li će se skripte pokretati u paraleli ili će mi pokretanje druge prekinuti prvu? Pokretat ce se paralelno al sa nekim primitivnim lock-om bi vjerovatno i o tome mogao voditi racuna.
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|