Cron жадвалига * * * * * ёзиш жуда осон: вазифа ҳар дақиқада ишга тушади ва сиз натижани деярли дарҳол оласиз. Аммо бу оддий қатор кунига 1440 марта, ойига эса қирқ мингдан ортиқ марта янги жараён очади. Агар ҳар бир ишга тушиш ярим сонияда тугайдиган енгил текширув бўлса, зарар сезилмайди. Лекин кўпинча бу ерда бутун сайт фреймворки юкланади, базага уланиш очилади ва иш бўлмаса ҳам ресурс сарфланади. Шу мақолада ҳар дақиқалик cron серверга айнан нима қилишини ва ундан қандай оқилона фойдаланишни кўриб чиқамиз.
Ҳар бир ишга тушиш нимага тушади
Cron PHP скриптини чақирганда сервер янги PHP жараёнини яратади, интерпретаторни юклайди, скрипт кодини ўқийди ва компиляция қилади. WordPress ёки Laravel каби тизимда бунинг устига бутун ядро, плагинлар ва созламалар юкланади, кўпинча базага бир нечта сўров юборилади. Бу ишларнинг ҳаммаси "бажариладиган вазифа борми?" деган саволга жавоб бериш учун қилинади, жавоб эса аксарият ҳолларда "йўқ" бўлади. Яъни процессор вақти ва хотира фойдали иш учун эмас, балки доимий тайёргарлик учун сарфланади.
Shared хостингда битта серверда юзлаб сайтлар ишлайди. Ҳар бир мижоз ўзининг бир-иккита ҳар дақиқалик вазифасини қўшса, дақиқа бошида бир вақтнинг ўзида кўплаб жараёнлар уйғонади. Бу юклама чўққиси барча сайтларнинг жавоб тезлигига таъсир қилади, шу жумладан сизнинг сайтингизга ҳам. Шу сабабли кўп хостинг тарифларида процессор ва жараёнлар сонига чегара қўйилади ва тез-тез ишлайдиган оғир cron айнан шу чегарага биринчи бўлиб урилади.
Устма-уст тушиш: энг хавфли ҳолат
Муаммо айниқса скрипт бир дақиқадан узоқроқ ишлаганда кучаяди. Фараз қилайлик, ташқи API секин жавоб беряпти ва скрипт 3 дақиқа кутиб қолди. Шу вақт ичида cron яна икки нусхани ишга туширади, улар ҳам кутиб қолади, кейин яна. Бир неча дақиқада ўнлаб бир хил жараён хотирани тўлдиради, базада уланишлар сони чегарага етади ва сайт "Database Error" бера бошлайди. Бундай занжирли қулаш кўпинча тунда, ҳеч ким кузатмаётган пайтда юз беради.
Бунинг олдини олишнинг энг оддий усули — flock билан қулф қўйиш. У олдинги нусха тугамагунча янгисини ишга туширмайди ва шунчаки ўтказиб юборади:
* * * * * /usr/bin/flock -n /tmp/navbat.lock /usr/bin/php /var/www/user/data/www/misol.uz/cron/navbat.php >> /var/www/user/data/logs/navbat.log 2>&1
wget ёки curl орқали ўз сайтингизни чақириш
Баъзи қўлланмалар cron'да wget -q -O - https://misol.uz/cron.php каби буйруқ ёзишни маслаҳат беради. Бу ҳолатда вазифа веб-сервер орқали ўтади: у PHP-FPM ишчиларидан бирини банд қилади, сўров ташриф буюрувчилар билан бир навбатда туради ва вақт чегарасига ҳам бўйсунади. Ҳар дақиқада шундай чақириш ҳақиқий фойдаланувчилар учун мўлжалланган ишчиларни эгаллайди. Иложи бўлса скриптни тўғридан-тўғри PHP CLI орқали ишга туширинг, чунки у веб навбатга таъсир қилмайди ва узоқ ишлар учун қулайроқ.
Қайси вазифаларга ҳақиқатан ҳар дақиқа керак
Ҳар дақиқалик частота фақат кечикиш сезиларли зарар келтирадиган жойда ўзини оқлайди: тўлов ҳолатини текшириш, SMS навбатини жўнатиш ёки тасдиқлаш кодларини юбориш. Валюта курсини янгилаш, sitemap яратиш, эски сессияларни тозалаш ёки статистика йиғиш учун ҳар 15-30 дақиқа, ҳатто кунига бир марта ҳам етарли. Ҳар бир вазифа учун "бу натижа 10 дақиқа кечикса нима бўлади?" деган саволни беринг. Агар жавоб "ҳеч нарса" бўлса, частотани камайтиринг.
| Вазифа | Оқилона частота | Cron ифодаси |
|---|---|---|
| Тўлов ҳолатини текшириш | ҳар 1-2 дақиқа | */2 * * * * |
| Валюта курсини янгилаш | ҳар 30 дақиқа | */30 * * * * |
| Sitemap яратиш | кунига 1 марта | 15 4 * * * |
| Эски файлларни тозалаш | ҳафтасига 1 марта | 30 3 * * 0 |
Яна бир фойдали одат — вазифаларни соат бошига эмас, тасодифий дақиқага қўйиш. Кўпчилик 0 * * * * ёзгани учун ҳар соат бошида сервер юкламаси кескин ошади. 17 * * * * каби ёзув ўша чўққидан қочишга ёрдам беради.
Енгил текширув, оғир иш фақат керак бўлганда
Агар вазифа ҳақиқатан тез-тез текширилиши керак бўлса, скриптнинг бошини иложи борича енгил қилинг. Аввал арзон текширув бажарилсин — масалан, навбат файлининг мавжудлиги ёки базадаги битта оддий сўров — ва фақат иш бор бўлса фреймворк юклансин. Бунда ишга тушишларнинг аксарияти бир лаҳзада тугайди.
<?php
// cron/navbat.php
if (!file_exists(__DIR__ . '/../data/navbat.flag')) {
exit; // ish yo'q, freymvork yuklanmaydi
}
require __DIR__ . '/../bootstrap.php';
// ... navbatni qayta ishlash ...
unlink(__DIR__ . '/../data/navbat.flag');
Оғир, лекин шошилинч бўлмаган ишларни эса паст устуворлик билан ишга тушириш мумкин. nice ва ionice буйруқлари жараёнга процессор ва диск навбатида камроқ улуш беради, шунда сайт ташриф буюрувчилари секинлашувни сезмайди:
15 4 * * * /usr/bin/nice -n 19 /usr/bin/ionice -c3 /usr/bin/php /var/www/user/data/www/misol.uz/cron/sitemap.php >> /var/www/user/data/logs/sitemap.log 2>&1
Амалий мисол: клиника сайти
Тошкентдаги хусусий клиника сайтида беморларга қабул эслатмасини юборувчи скрипт ҳар дақиқада ишларди. Ҳар сафар у бутун CMS'ни юклаб, эртанги куннинг барча ёзувларини базадан тортиб оларди, гарчи эслатмалар кунига атиги бир неча ўнлаб бўлса ҳам. Эрталабки ташрифлар пайтида сайт секинлашди, хостинг панелида эса процессор чегараси огоҳлантиришлари пайдо бўлди. Скрипт ҳар 10 дақиқада ишлайдиган қилиб ўзгартирилди, унга flock қўшилди ва сўров фақат ҳали эслатма юборилмаган ёзувларни оладиган қилинди. Беморлар эслатмани аввалгидек ўз вақтида олишда давом этди, сайт эса эрталаб ҳам тез ишлай бошлади.
Юкламани ўзингиз ўлчаб кўринг
Бир ишга тушиш қанча вақт ва хотира олишини билиш учун скриптни терминалда /usr/bin/time -v билан ишга туширинг. Натижада "Elapsed (wall clock) time" ва "Maximum resident set size" қаторлари кўринади. Бу рақамни кунига неча марта ишга тушишига кўпайтирсангиз, вазифа умумий қанча ресурс олиши аниқ бўлади.
/usr/bin/time -v /usr/bin/php /var/www/user/data/www/misol.uz/cron/navbat.php
sayt.uz хостингида cron вазифаларининг рўйхати ва жадвали ISPmanager панелида кўринади, панелга эса sayt.uz кабинетидан кирасиз. Агар сайтингиз секинлашиб, сабаби cron'дами ёки йўқми аниқ бўлмаса, техник ёрдамга мурожаат қилинг — сервер томонида қайси жараёнлар кўп ресурс олаётганини кўриш мумкин.