v2.5.2
Giriş yap

PHP kodunu her n saniyede bir çalıştırmak

r00t
251 defa görüntülendi

Selamlar;
Site içerisinde çeşitli durumlarda ajax ile çağrılan bir PHP dosyam var.
Çok fazla request oluşturma durumuna karşılık, kodun her 2 dakikada bir çalışması için komik ama günü kurtaracak bir çözüm bulmuştum.
Benim çözümüm şu şekildeydi;

$currMinute = date("i");
if ($currMinute % 2) {
    exit;
}

Böylece bu dosyadaki kodlar, sadece mevcut dakika tek haneli ise çalışacak, çift haneli dakikada gelen istekler blocklanıyordu.

Ancak sadece belirli 60 saniyeler içerisinde çalıştır, sonraki 60 saniyede gelenleri blockla durumu çok fazla geciktirmeli bir hal alıyor.
Bu basit kodu nasıl revize edersem, örneğin sadece 25 saniye blockla - 25 saniye çalıştır gibi "n" saniye blockla diyecek şekilde ayarlayabilirim?

umarım anlatabilmişimdir, teşekkürler

Cevap yaz
Cevaplar (4)
ebykdrms
74 gün önce

Bu kodda kullanıcı sadece 2'ye bölünmeyen dakikalarda işlem yaparsa exit komutu işlemeyip kod devam edecek ve PHP sonraki işlemleri yapacak.
Kullanıcı 13.50.14, 13.50.46, 13.50.55 gibi saatlerde istek atarsa exit komutu çalışır ve PHP diğer işlemleri yapmaz.
Kullanıcı 13.49.14, 13.49.46, 13.49.58 gibi saatlerde bir işlem yaparsa tüm istekleri PHP tarafından kabul edilmiş olur.

Amacımız "bir kullanıcının bir istek yaptıktan sonra 1 dakika boyunca başka işlem yapmasını engellemek" ise bu kod hatalı çalışıyordur diyebiliriz.
PHP, çift dakikalarda gelen hiçbir isteği yanıtlamıyor. Ama tek dakikalarda gelen tüm istekleri yanıtlıyor.
Kurgunu bilmediğim için belki de bunda bir hata yoktur tabi, sen zaten bunu amaçlamış olabilirsin.

Eğer bunu amaçlamışsan (her kullanıcının sadece tek dakikalarda yaptığı tüm istekler çalışsın)
if koşulundaki "tek dakika" yani "her 2 dakikada bir" ifadesi yerine "her N saniyede bir" ifadesini koymak istiyorsun.
Bu durumda N = 30 dersek, "her 30 saniyede bir gelen istekleri kabul et" demek istiyorsun.
Bu durumda "H", "i", "s" değerlerine değil de doğrudan timestamp'e bakarak işlem yapmak gerekir.

Alıntı: PHP tarih ve zaman ifadelerinde unix zaman damgasını kullanır. Unix timestamp en basit ifadeyle “1 Ocak 1970 00:00:00” tarihinden itibaren günümüze kadar geçen saniye sayısıdır.
Kaynak: https://www.phpr.org/php-ile-tarih-ve-saat

Bu durumda timestamp'i kullanarak her N saniyede bir çalışacak şekilde bir kontrol yapabiliriz. Örneğin, N = 25 saniye olarak ayarlamak istersen, şu şekilde bir çözüm uygulayabilirsin:

$currTimestamp = time();
if ($currTimestamp % 50 >= 25) exit;

Bu kod parçası, her 50 saniyede bir çalışacak ve sadece ilk 25 saniye içinde gelen istekleri kabul edecektir. Diğer 25 saniyede gelen istekler ise bloklanacaktır. Buradaki time() fonksiyonu, o anki Unix zaman damgasını verir ve bu değerin 50'ye bölümünden kalan, 25'ten büyük veya eşitse, exit komutu çalışarak PHP işlemlerini durdurur.
Eğer farklı bir süre için ayarlamak istersen, örneğin her 60 saniyede bir 20 saniye çalışsın ve 40 saniye bloklasın istersen, kodu şu şekilde değiştirebilirsin:

$currTimestamp = time();
if ($currTimestamp % 60 >= 20) exit;

Burada karşımıza 2 ifade çıkıyor: "Her X saniyede bir N saniyelik zaman diliminde çalışsın, aksi halde exit ile bloklansın."
Bunu da fonksiyonel bir hale getirmek daha uygun olacaktır. Bu işlemi yapan fonksiyon şu şekilde yazılıp kullanılabilir:

function isRequestAllowed($interval, $activePeriod) { 
    return (time() % $interval) < $activePeriod;
}

Artık "her 60 saniyede bir, sadece ilk 20 saniyede gelen istekleri kabul et" ifadesinin karşılığı:

if (!isRequestAllowed(60, 20)) exit;

Bu durumda örneğin,
şu saat aralıklarında yapılan tüm istekler bloklanır:
13:00:20 - 13:00:59, 13:01:20 - 13:01:59, 13:02:20 - 13:02:59, 13:03:20 - 13:03:59

şu saat aralıklarında yapılan tüm istekler bloklanmadan işleme alınır:
13:00:00 - 13:00:19, 13:01:00 - 13:01:19, 13:02:00 - 13:02:19, 13:03:00 - 13:03:19

Amaaaa, eğer senin asıl amacın örneğin bir kullanıcının sadece N=20 saniyede bir işlem yapabilmesi ise farklı bir kurgu gerekir.
Yani "bir kullanıcı 13:00:05'te istek yaptıysa bir daha 20 saniye boyunca (13:00:25'e kadar) yapılan isteklerine yanıt gelmesin" diyorsan orada farklı bir kurgu devreye girer.
Bu durumda isteğe gelecek yanıt sunucu zamanına değil kullanıcının istek yaptığı zamana bağlı olur ve her kullanıcının kendine özgü bir zamanı olur.

Veya amacın "bir kullanıcı 13:00:05'te istek yaptıysa diğer tüm işlemlerini 20 saniye içinde (13:00:25'e kadar) yapsın, yani 20 saniye boyunca bu kullanıcıya işlem yapma izni verilsin. 20 saniyeyi aşarsa yeni istek için 40 saniye beklesin." diyorsan burada da başka bir kurgu devreye girer.

Nitekim, senin kodundan yola çıkarak cevap yazdım ama senin kurgun farklıysa ona göre daha detaylı şekilde ayrı bir yeni soru açmalısın.

r00t
74 gün önce

@ebykdrms abi eline koluna çabana sağlık ne diyeyim. blog yazısı gibi olmuş :) kod örneğini koyman bile yeterliydi aslında benim için; time'yi bölmek aklıma gelmemişti hiç. ama bu şekilde yazdığın için, benzer soru işaretiyle bu yazıya denk gelen herkes için faydalı olacaktır. tekrar teşekkürler; tam aradığım cevaptı.

r00t
75 gün önce

@fazilmertvural cron jobs'luk bir durum değil aslında bakarsan; ziyaretçi bazlı bir durum. ziyaretçi sayfadayken atıyorum 5 saniyede bir oraya dosyaya istek atıyor ve response alıyor.

fazilmertvural
75 gün önce

Merhaba bunun yerine eğer cPanel kullanıyorsanız Cron Jobs modülünü kullanmanız daha sağlıklıdır. İyi çalışmalar.