[ Predrag Supurovic @ 05.12.2019. 13:24 ] @
Imam sledeću situaciju:

Web servis generiše slike na zahtev. Pošto generisanje slike traje, napravio sam php skript za keširanje slika na drugom serveru tako da tražene slike prikazujem iz keša.

Procedura je sledeća

- klijent zatraži sliku od keša
- keš proveri da li ima tu sliku i da li je slika nije previše stara i ako je tako prosledi klijentu sliku
- ako slike nema u kešu ili je ima ali je stara, onda povuče novu sliku od servisa, sačuva je i prosledi klijentu

To radi kako treba.

Ako slike nema u kešu, klijent svakako mora da sačeka dok keš se povuče sliku od servisa da bi je prosledio.

Problem koji se javlja je da većinu slika klijenti dovoljno retko traže tako daispada da svaki put kada neki klijent zatraži sliku ona je već zastarela u kešu, pa mor da čeka dok keš ažurira sliku.

Pošto nije kritično da klijent u momentu kada traži sliku mora da dobije u tom trenutku ažurnu verziju, hteo bih da izbegnem to čekanje ako sliku imam u kešu čak i ako je ona zastarela.

Ideja je da ako keš ima sliku odmah tu sliku pošalje klijentu a tek onda proveri da li je slika zastarela pa ako jeste ažurira je tako da za sledeći upit za istu sliku ima ažuriranu verziju.

Najbolje što mi je palo na pamet je da keš slike ne ažurira direktno prilikom upita nego da taj posao delegira nekom paralelnom procesu koji će to da radi u pozadini, na primer nekom cron jobu.

Ima li neko ideju da li bi to moglo da se izvede bez cron job-a? Suština je da to bude jednostavno za održavanje. Naravno, radi se o klasičnom hostingu tako da korisnik nema root pristup serveru i sve poslastice koje dolaze sa tim.

[ Tpojka @ 05.12.2019. 13:34 ] @
Citat:
Pošto nije kritično da klijent u momentu kada traži sliku mora da dobije u tom trenutku ažurnu verziju, hteo bih da izbegnem to čekanje ako sliku imam u kešu čak i ako je ona zastarela.


Koristim Laravel i uradio bi' taj dio na Event/Listener a u listener-u bi' postavio dispatch na Job tako da response ne čeka osim ako baš nema te slike. Ako sam dobro uhvatio šta treba.
Mimo laravel-a vjerovatno slično s tim što treba sve ove segmente napraviti (event/listener, Queue/Job...).
[ Deunan @ 05.12.2019. 15:57 ] @
Mozda sam pogresno razumeo, ali onda ce klijenti uvek dobijati zastarelu verziju.
Citat:
Ideja je da ako keš ima sliku odmah tu sliku pošalje klijentu a tek onda proveri da li je slika zastarela pa ako jeste ažurira je tako da za sledeći upit za istu sliku ima ažuriranu verziju.

Ako klijenti retko traze sliku, ti dok napravis azuriranu verziju, do sledeceg klijenta ona je istekla. Tako da i njemu dajes zastarelu sliku, generises novu koja ce da istekne do sledeceg klijenta i tako u krug.

Ako ces ipak tako, nek kes prosledi sliku i posalje zahtev web servisu za novu sliku. Ne treba ti cron.
[ Shadowed @ 05.12.2019. 16:49 ] @
Nece dobijati uvek zastarelu sliku. Ako je npr. timeout slike jedan mesec a cron job radi jednom dnevno i generise novu sliku za svaku koja istice sutra, imace uvek svezu.
@Pedja, cron job ce ti resiti problem ali imas i negativne strane kao sto je npr. to da ces generisati nove verzije slika koje mozda nikad nece biti trazene. Sad, to mozda i nije problem, zavisi od detalja situacije kod tebe (koliko je ukupno slika, koliko se cesto traze, da li se traze ravnomerno sve ili neke manje, neke vise.

Kakva je aplikacija u pitanju? Ako je klasicna web strana, ono sto mozes uraditi da ti donekle smanji cekanje je da ucitavanje strane okine generisanje potrebnih slika (ti u tom trenutku vec znas koje slike ce biti prikazane). Tako ce generisanje raditi dok web strana ide do klijenta, bude parsirana i zahtevi za slikama budu poslati. Ovo moze biti jos efikasnije ako se slike ne zahtevaju odmah pri ucitavanju web strane nego naknadno, na osnovu akcije korisnika.
Opet, zavisi od situacije. Npr. ako ti generisanje slike traje 2sec a ovako obavis 0.5sec posla pre nego sto stigne zahtev, ima smisla. Ako traje 10sec, onda usteda od 0.5sec i nije nesto.
[ nkrgovic @ 05.12.2019. 17:25 ] @
Ti mozes da imas simulirani cron, tj. deo procesa koji se okida svaki put kad se bila koja strana okine - bolje od toga ne moze, ako imas shared hosting...

Ono sto meni nije jasno, zasto, aman, za tako neki slozeni projekat nemas bar VPS? Pristojan VM moze da se uzme za 20 EUR mesecno, nadjes nekog da ti to odrzava part-time i spakujes na to sve sto imas.... Nije to toliko posla da bi ti neko to ko zna koliko naplatio....
[ Zlatni_bg @ 05.12.2019. 19:07 ] @
Sta je ovde cilj tog kesiranja? Cuvanje BW-a, resursa ili nesto drugo?

Ako cemo da izbegnemo Laravel ili neki drugi FW, ja bih ovde ubacio bar bazu podataka i cuvao timestampove. Na glavnom serveru radio proveru pri svakom requestu da koji je stariji timestamp, ili ako ti nije vremenski kriticno kako kazes, mozes da nadjes neki drugi "okidac", tipa po kolicini slika, itd. Ne mora cron ali sve zavisi sta tacno pravis. Generalno cron i nije nesto sto bi ti pomoglo ovde, vise ti treba mikroservis koji bih ja uredio preko tih timestampova. A mozes i njega da pokreces na recimo pola sata i slicno. Imas li composer bar?

Mozes i ultra-jeftino da zakupis neki cloud servis gde bi drzao te "triggere", gde se uglavnom placa samo CPU vreme i slicno. Mada za takve stvari, kolege admini i devopsi ce bolje posavetovati.

https://aws.amazon.com/free/

https://aws.amazon.com/lambda/?did=ft_card&trk=ft_card

Mozes da koristis lambdu koja je always free za 1mil zahteva mesecno. Dobijes *do* 3.2 miliona sekundi izvrsavanja. Bolje od crona.
[ nkrgovic @ 05.12.2019. 19:26 ] @
Iskreno, ja bi to resio na par nivoa: dodao expires tagove na assets, pa preko toga stavio lepo neki klasican CDN, moze i free CloudFlare - i to bi radilo samo tako. Problem je sto to zahteva da se podesi nginx za odradjeni /location i doda sve sto treba - a to na shared hostingu ne moze. Zato sam i rekao neki VPS. :)

Takodje, "nesto da zameni cron", samo da cron ne bi bio u igri je glupo - jer se opet, reasava VPS-om od 10-20EUR mesecno. Ja bi za laravel mozda razmislio o queue-u, pa sve to orkestrirao kroz supervisord, to je nekako vise "native", uz eventualno i neki queue ako treba tipa ZeroMQ, ili makar redis koji glumi queue, sto je realno bolje resenje, jer em je brz, em dovoljno dobro radi, em moze da radi i za kesiranje... ali opet, sva ta resenja nisu za shared hosting.

Shared hosting je za Wordpress sajt, mozda, koji ima par desetina posetilaca - a i tu se, realno, uzme neki managed VPS barem. Bilo koja poslovna primena koja moze da opravda angazovanje developera da razvije custom resenje moze da opravda i par stotina evra mesecno za ops koji ce da tu pruzi neko odrzavanje, updates i slicno - i naravno SLA. Ako taj sajt donosi neke pare, onda zelis i da radi. Ako ti je skupo da platis da sajt radi, onda ne razumem sto placas hiljade evra da ga neko napravi....
[ Zlatni_bg @ 05.12.2019. 19:33 ] @
Ja posmatram ovakva pitanja kao da neko malo dete koje uci neki programski jezik pokusava besplatno da nadje workaround :) Iako je u pitanju cenjeni clan foruma, sa takvom postavkom menjam razmisljanje o problemu - generalno ne znamo nista o tome sta mu treba i zasto, samo znamo da je free hosting i da ocigledno ne postoje dodatni troskovi u planu. S toga - lambda :)

Ne treba ignorisati te AWS besplatne servise. Umeju da nadju primenu, pa makar da pokrece neku udaljenu PHP skriptu u odredjeno vreme :D
[ nkrgovic @ 05.12.2019. 21:22 ] @
E, super je lambda, daleko od toga. Radice to ok, ako je latencija prihvatljiva. Again, ima i t3.micro free instanca, kad smo kod free....
[ Zlatni_bg @ 05.12.2019. 21:26 ] @
Ima i Azure functions istu pricu, cak moze da radi i kompletan CI/CD 10 PHP aplikacija tamo - samo ce morati da se snadje za DB. Nista drugo na pamet ni ne pada a da je besplatno na duze staze.

Prednost Azure-a je sto podrzava PHP, dok AWS "pozdrzava" uz dosta zezanja.
[ dakipro @ 05.12.2019. 21:36 ] @
Ako pricam o besplatnom cron jobu, prvi rezultat googla daje https://cron-job.org/en/ , mozda pomogne
[ Shadowed @ 05.12.2019. 21:47 ] @
Citat:
Zlatni_bg: Ja posmatram ovakva pitanja kao da neko malo dete koje uci neki programski jezik pokusava besplatno da nadje workaround :) Iako je u pitanju cenjeni clan foruma, sa takvom postavkom menjam razmisljanje o problemu - generalno ne znamo nista o tome sta mu treba i zasto, samo znamo da je free hosting i da ocigledno ne postoje dodatni troskovi u planu.


Definitivno nema dovoljno informacija ali moj "educated guess" je da se slika generise na osnovu nekih podataka (tipa neki grafik ili tako nesto) i da generisanje traje neko vreme tako da ne zeli svaki put to da radi (da ne bi svaki put korisnik cekao) pa zato kesira vec napravljenu sliku. Medjutim kada se podaci izmene/dopune, potrebna je nova slika.
[ Deunan @ 05.12.2019. 22:45 ] @
Verovatno je ovo sto kaze Shadowed.

Sme li CURL da se koristi? To bi trebalo da podrzava svaki hosting.

1. Napravi stranicu na kes servisu koja ce da zove servis za pravljenje slika i da cuva slike, recimo http:// kes-servis/regenerate
2. Kad klijent zatrazi sliku i ako je slika istekla, posalji zahtev za novu sliku, a njemu prosledi staru:
Code:

$ch = curl_init("http:// kes-servis.com/regenerate");  // Servis posalje "samom sebi" post request
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, 
http_build_query([
    'image'=>'ime_slike.jpg'           // Stavi parametar da znas koja slika mora da se azurira (mozes i neki token zbog sigurnosti)
]));
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1);          // OBAVEZNO: STAVI TIMEOUT u MILISEKUNDAMA DA NE MORAS DA CEKAS RESPONSE
$response = curl_exec($ch);
curl_close($ch);

// Vrati korisniku staru sliku, ili kako ti vec funkcionise servis
echo "<div><img src="stara_slika.jpeg" /> </div>"

U sustini, kes servis posalje POST request samom sebi i ODMAH ga "ubije" TIMEOUT-om da ne ceka response, vratis klijentu staru sliku.
kes-servis.com/regenerate skripta ce u pozadini da kontaktira servis za pravljenje slika i da sacuva novu azuriranu verziju.
Mozes i ajax-om da proveris sliku posle par sekundi i da update-ujes klijenu staru sliku.


[ Branimir Maksimovic @ 06.12.2019. 05:13 ] @
Svako resenje koje ne uikljucuje daemon proces koji osvezava kes je prilicno clumsy. Ne treba ti kron nego tvoj proces koji ce da osvezava slike, recimo LRU ne mora sve stalno nego po prioritetu koji formiras
na osnovu toga koliko puta je kojoj i kada slici pristupljeno.
[ Predrag Supurovic @ 06.12.2019. 08:36 ] @
Evo da dam nekoliko pojašnjenja.

Radi se o renderingu tile sličica za mapu i njihovom učitavanju u klijentske web čitače. Zbog potencijalno velikog optererećenja servera koji renderuje sličice (a koji baš i nije neki reprezentativan računar), napravio sam cache preko koga se preuzimaju sličice.

Rendering jedne sličice ume da potraje i to utiče na prikazivanje mape koja paralelno povlači veliki broj sličica. Možee pogledati na http://ue.cache.osmsrbija.iz.rs kako sada radi keširanje - kada odete ne deo mape koji nije keširan (ili sličice treba da se osveže), usporenje je do neupotrebljivog.

Zato je prioritet da se mapa pre svega prikaže pa makar i ne bile sve sličice ažurne.

Stvar je potpuno nekomercijalna tako da nemam na raspolaganju rešenja koja podrazumevaju plaćanje jakih servera i slično.

Rešenje da se sve sličice nezavisno periodično ažiriraju nije prihvatljiva jer sličica ima mnogo pa bi taj proces trajao veoma dugo a verovatno i nepotrebno. Zato je pristup da se keširanje radi na upit. Osvežavaju se one sličice koje korisnici zaista i pregledaju.

To bi tako radilo i sa cron-jobom: keš bi kada utvrdi da neku sličicu treba ažurirati, negde sačuvao instrukciju za cron job, a ovaj bi povremeno proveravao da li ima nešto za ažuriranje i ažurirao samo to.

Moja ideja je da napravim keš skriptu koju svako može po potrebi da stavi kod sebe i sam sebi kešira sličice. To podrazumeva da stvar treba da bude jednostavna i da se postavlja bez mnogo komplikacija na bilo kakvom hosting serveru bez bilo kakvih preduslova da korisnik mora da ime neku određenu platformu, CMS ili već šta, ili da mora da radi neka specifična podešavanja servera, već je dovoljno samo da ima php. Petljancija sa cron job-om je najdalje što bih išao, ako ne mogu da izbegnem.






[ Predrag Supurovic @ 06.12.2019. 08:46 ] @
Citat:
Deunan:
U sustini, kes servis posalje POST request samom sebi i ODMAH ga "ubije" TIMEOUT-om da ne ceka response


Vidiš ovo sa TIMEOUT mi nije palo na pamet. Možda upali ako veb server ne ubije proces čim vidi da je klijent "prekinuo" konekciju.


Razmišljao sam da veb čitaču prvo pošaljem sliku a onda u istom procesu da krenem u osvežavanje nadajući se da će veb čitač početi da prikazuje sliku čim dobije podatke bez obzira što sama konekcija još uvek nije prekinuta.
[ bojan_bozovic @ 06.12.2019. 10:14 ] @
Resenje ti je da sve postavis na svoj server, i da koristis cron. Zasto? Zato sto ce slicice da se kesiraju vec prema tome koje su najcesce u upotrebi, a te podatke imas na svom serveru, nema ih neko ko ce da postavi skriptu na svoj deljeni hosting.
Eventualno napravi api, gde moze skripta da izvrsi upit sta treba da se kesira a sta ne. Tada moze ta skripta da bude i na remote serveru, jer moras da sacuvas i bandwidth, da ga ta remote skripta ne trosi previse, i da moze da se izvrsava sa skromnim resursima.
I na jedan i na drugi nacin imaces bolje performanse, sto ti je potrebno.
[ Zlatni_bg @ 06.12.2019. 16:53 ] @
Citat:
nkrgovic:
E, super je lambda, daleko od toga. Radice to ok, ako je latencija prihvatljiva. Again, ima i t3.micro free instanca, kad smo kod free....


Free je na 12 meseci, ja vise gledam ono sto je free forever :) Ima ja mislim f3 ili tako nesto, ali izgleda ce od sad da naplacuju zauzece IP adrese. Nije mi bas najjasnije ono sto pise tamo (uvek su ti cloud servisi ultra teski za kalkulaciju), ali IP adresa bi kostala kao neki minimalistican VPS. U sustini sa ovim serverless stvarima poput Lambde, Azure Functionsa itd, jedini problem na koji se nailazi je DB server. Za to je potrebna neka VM instanca uglavnom, nisam jos video da iko pruza hostovanje (ne racunam db4free itd) db servera za dzabe.
[ agvozden @ 07.12.2019. 08:43 ] @
Nešto slično koristim za male sličice - thumbnails. One su u cache folderu. Periodično ih obrišem, ili po potrebi. Stare slike premeštam u backup folder.
Kada apache .htaccess ili nginx vidi da nema slike, onda pokuša da kreira thumbnail, ili prebaci sliku iz backup-a.
Na ovaj način mogu da poskidam male sličice koje više nisu potrebne, ili da ih osvežim.
Ne proveravam koliko su stare slike, to mi nije potrebno, ali imam taj podatak u bazi slika.
[ S A J A @ 07.12.2019. 09:17 ] @
Ja bi napravio sistem sa dva zahteva. Inicijalno se preuzmu slike iz keša pa se onda na strani klijenta, za svaku dobijenu bajatu sliku, generiše novi zahtev, može i na drugi server, koji renderuje svežu sliku, vraća nazad i kopira na keš.