Кой е най-добрият начин за стартиране на PHP скрипт в определен момент?

Имам сайт, в който търговете приключват в различно време. Трябва да изпратя автоматичен имейл до продавача и купувача след приключване на търга, за да ги уведомя за края на търга и резултатите. Очевидно нямам търпение някой да зареди страницата, за да изпълни скрипта, така че има ли добър начин да автоматизирам това, като проверявам текущия час и го сравнявам с часа на края на търга и изпълнявам този скрипт?

Сайтът е на UNIX сървър, така че задачата на cron е опция, но се притеснявам, че стартирането на задача на cron като тази ще натовари доста сървъра.


person Budove    schedule 28.02.2013    source източник
comment
Мога ли да попитам каква сървърна инфраструктура използвате? Предполагам, че използвате механизъм за таймер в нещо различно от PHP? Ако използвате нещо друго, препоръчвам ви да прикачите някакъв код към този механизъм на таймера, който също така изпълнява скрипт за изпращане на имейл, когато таймерът изтече.   -  person L0j1k    schedule 28.02.2013
comment
Не знам за никакъв вид таймер, който бих могъл да използвам, освен може би javascript, работещ на страницата. Не исках да използвам javascript, защото всъщност се страхувах, че някой ще манипулира това и ще измами на търг.   -  person Budove    schedule 28.02.2013
comment
Какво използвате тогава, за да определите кой ще спечели търга? Как можете да определите (с точност) кой печели? Бих бил много внимателен да използвам стабилен механизъм за таймер в задната част (като например в JavaScript в Node.js или Perl, или Python... или всичко наистина освен PHP). Започвам да добивам представа как работи вашият таймер, задейства се и проверява файл/база данни, когато потребител посети страницата? Сега може да звучи трудно и може би ненужно, но с нарастването на приложението ви ще бъдете много доволни, че сте създали основен таймер във фонов режим, който изпълнява всички тези механизми.   -  person L0j1k    schedule 28.02.2013
comment
Да, но страницата е настроена да се опреснява на всеки 60 секунди. Имате ли някакви предложения как да приложите това? В момента имам крайна дата и час на търга и когато страницата се зареди, тя сверява това с текущата дата и час.   -  person Budove    schedule 28.02.2013
comment
Добре, но какво се случва, когато потребителят просто напусне страницата? Какъв механизъм е въведен, за да се гарантира, че търгът приключва правилно и правилният потребител(и) е уведомен(и)? Със стабилен бекенд като JavaScript /Node (или Perl или каквото и да е, ако не харесвате Node), можете да имате текущ процес, за да направите изчисленията и да задействате това, което трябва да се задейства, както и да изпратите имейли с известия. Освен това, тъй като е в задната част, цялото ви приложение няма да зависи изцяло от взаимодействието на потребителя, за да функционира правилно. Бих казал, че да го правиш по начина, по който си сега, е по-опасно.   -  person L0j1k    schedule 28.02.2013
comment
Макар и само защото целият процес разчита на потребителя (да не говорим за последиците за сигурността в процеса).   -  person L0j1k    schedule 28.02.2013
comment
Е, това е моят проблем... опитвайки се да уведомя правилния потребител. Предполагам, че ако потребителят не взаимодейства със страницата, тогава търгът не трябва да приключи, но когато го направи, времевата разлика се изчислява и потребителят се уведомява, че търгът е приключил. Предпочитам да направя това с JavaScript, но не съм много добър с него.   -  person Budove    schedule 28.02.2013
comment
Е, за щастие, JavaScript е наистина лесен за работа, особено ако знаете достатъчно PHP, за да правите това, което вече правите. Знам, че звучи като монументална задача, но ще ми благодарите по-късно, когато се сблъскате с огромни, огромни проблеми със задачите, когато 1) приложението ви се мащабира или 2) потребителите ви започнат да се оплакват, че не са получили известие, че са загубили или спечелиха, докато не посетят страницата отново. В края на краищата не всеки седи и щраква върху опресняване в eBay.   -  person L0j1k    schedule 28.02.2013
comment
Добре, след като помислих още малко, мисля, че има JavaScript таймер на страницата, който проверява крайната дата/час на търга и започва обратно броене, докато страницата е отворена. Ако приключи, докато страницата е отворена, наддаването се затваря. На всичкото отгоре, cron задача, която се изпълнява на всеки 60 сек. който търси изтекли търгове и ги затваря, както и изпраща уведомителни имейли. Благодаря за помощта.   -  person Budove    schedule 28.02.2013
comment
Съвет: Никога не се доверявайте на клиентите си да вършат критична работа. Това, което бих направил в тази ситуация, за да разреша проблема бързо, е да създам Perl скрипт (тъй като просто избираме един, който знаем как да пишем), който има достъп до базата данни с търгове и съдържа сърдечния ритъм на ВСИЧКИ търгове, което означава, че следи системно време и КРАЯ на всички търгове. След това, когато търгът приключи, той се свързва със специално написана локална уеб страница, която извършва всички ваши имейли и сортиране на бази данни в PHP. Това решение не е най-доброто, но е бързо решение и спира да разчита на клиента за важни неща.   -  person L0j1k    schedule 28.02.2013


Отговори (5)


Cron задача се изпълнява най-много веднъж на минута.

Какъвто и товар да генерира на сървъра, наистина зависи от вида скрипт, който ще стартирате. Между другото, предполагам, че използвате cli за изпълнение на скрипта (вместо просто да правите curl http://mysite.com.

Ако вашият скрипт отнема повече от една минута (трябва да наблюдавате това), просто:

  • Увеличете интервала между изпълненията или,
  • Използвайте заключващ файл, за да се уверите, че два екземпляра на вашия скрипт не могат да се изпълняват едновременно.

    if (($fp = fopen('/tmp/mylockfile', "r+")) === false) {
        die("Could not open lock file");
    }
    if (!flock($fp, LOCK_EX | LOCK_NB)) {
        die("Could not obtain lock");
    }
    // run your code here
    
    // release the lock and close file
    fclose($fp);
    

OTOH Ако скриптът трябва да се изпълнява повече от веднъж в минута, ще ви е необходим изцяло различен механизъм.

person Ja͢ck    schedule 28.02.2013
comment
„трябва да сравните това“, не! трябва да се уверите, че вашият скрипт спира след 59 секунди! - person hek2mgl; 28.02.2013
comment
@hek2mgl Какво? Разбирате колко непрактично е това, нали? Освен ако не се шегувате разбира се. - person Ja͢ck; 28.02.2013
comment
Не, това е задължително! Правил съм това.. Имам опашка.. Спиране след края на опашката или 50 сек. Ако достигнат 50 секунди -› имейл до администратора. ТРЕВОГА! . това е добра работа - person hek2mgl; 28.02.2013
comment
@hek2mgl Един прост файл за заключване би бил достатъчен, който гарантира, че друго копие не може да работи заедно. - person Ja͢ck; 28.02.2013
comment
„Прост файл за заключване“ го направете с PHP (не пикантен). - person hek2mgl; 28.02.2013
comment
@hek2mgl Не съм сигурен какво имаш предвид с това. - person Ja͢ck; 28.02.2013
comment
не е пикантен, означава, че не е уязвим срещу условия на състезание, между другото отговорите ви са добре (сега). но така е и отрицателният отговор на @L0j1k. Не знам защо да гласувам против - person hek2mgl; 28.02.2013
comment
@hek2mgl Racy означава нещо съвсем друго, но използването на препоръчително заключване е приет начин за предотвратяване на многократни изпълнения. - person Ja͢ck; 28.02.2013
comment
съветващото заключване е добър начин да се справите с този проблем, стига да искате само един процес да изпълнява нещата. Ако трябва да мащабирате хоризонтално, това няма да е достатъчно. - person FoolishSeth; 28.02.2013

Въпрос: Кой е най-добрият начин за стартиране на PHP скрипт в определено време или интервал?
О: Използвайте cron

Q: cronjob създава ли голямо натоварване на сървъра?
A: Зависи от вашия скрипт. Но проверката дали даден търг трябва да бъде затворен, затварянето му и изпращането на два имейла не би трябвало да е твърде трудно. Не забравяйте да създадете някакъв вид заключващ файл, за да се уверите, че ако вашият скрипт работи по-дълго от зададения интервал, той няма да бъде изпълнен два пъти.

Q: изпълнение на скрипт с по-кратки интервали от 1 минута
A: Не мога да отговоря на този вместо вас. съжалявам :)

person stUrb    schedule 28.02.2013

Използвайте Cron. Тя ви позволява да изпълнявате всяка команда най-много веднъж на минута: http://clickmojo.com/code/cron-tutorial.html

Що се отнася до натоварването на сървъра, това обикновено няма да бъде проблем, освен ако не изпълнявате огромен брой извиквания на базата данни много често на сървър от много нисък клас. Говоря общо взето, но идеята е здрава.

Ако използвате нещо друго (освен PHP), за да стартирате своя механизъм за таймер на търга, препоръчвам ви да прикачите някакъв код към този механизъм за таймер, който също така изпълнява скрипт за изпращане на имейл, когато таймерът изтече до нула и определя победител.

person L0j1k    schedule 28.02.2013
comment
OP каза: задачата на cron е опция, но се притеснявам, че стартирането на такава задача на cron ще натовари доста сървъра. В случай, че се чудите, това не беше МОЕТО отрицание. - person Ja͢ck; 28.02.2013
comment
Не гласувах против мен, но вероятно защото казвате, че когато пожелаете. Това не е вярно, най-много 1 минута интервали. При търг това не е удобно. - person stUrb; 28.02.2013
comment
Добре, така че изпълнете опцията: Използвайте cron. Съжалявам, че не сте го разбрали. - person L0j1k; 28.02.2013
comment
Това е моята грижа. Изпращането на имейли може да стане тромаво за сървъра, ако използването на сайта нараства. Притеснявам се, че може да има 100 имейла за всяко cron задание... но ако скриптът изпраща 1 имейл на скрипт (вместо 100 BCC), биха ли изпратили едновременно? - person Budove; 28.02.2013
comment
Дори изпращането на стотици имейли на минута няма да доведе до това натоварване, за което трябва да се тревожите. Стотици имейли в секунда може би, но не и няколкостотин в минута. - person L0j1k; 28.02.2013
comment
И тогава е вероятно да се натъкнете на проблеми с маршрутизирането на пощата (т.е. задействане на флаг за спам при вашия интернет доставчик), преди да се натъкнете на проблеми със сървъра, обработващ изходящата поща. - person L0j1k; 28.02.2013
comment
Добре, благодаря ви за помощта. - person Budove; 28.02.2013
comment
Няма проблем. Надявам се да ви помогне. :) - person L0j1k; 28.02.2013

Стартирайте PHP скрипта като скрипт от командния ред. Това няма да натовари уеб сървъра - само натоварване на сървъра и можете лесно да го стартирате чрез CRON.

Ако добавите #!/usr/bin/php в началото на скрипта и промените бита за изпълнение на файла с chmod +x scriptname.php, можете директно да изпълните скрипта, без да го предавате през php

http://php.net/manual/en/features.commandline.php

person Geek Num 88    schedule 28.02.2013
comment
Е, с #!/usr/bin/php всъщност предава това през PHP, но директно на интерпретатора. - person L0j1k; 28.02.2013
comment
Съжалявам, имах предвид да го стартирам чрез php scriptname.php срещу scriptname.php - person Geek Num 88; 28.02.2013

Няколко неща, които трябва да направите, за да направите това:

  1. Съхранявайте нещо във вашата информация за търга, указващо дали вече сте изпратили този имейл или не (може да е булева стойност или дата на изпращане, която може да е нула). Въпреки че трябва да предположа, че трябва да направите нещо освен да изпратите този имейл? Искате ли да маркирате търга като затворен, за да не може повече да се наддава?

  2. Част от кода, който намира търгове, които се нуждаят от изпращане на този имейл: напр. те са приключили и все още не са им напомнени.

  3. Нещо за многократно изпълнение на част от кода във 2. Можете да използвате cron. Като алтернатива можете да напишете доста прост демон за unix, който работи постоянно в цикъл на (изчакайте поне няколко ms или повече; направете някои неща). Последното е много повече работа, но според мен мащабът е много по-добър. Вижте http://pear.php.net/package/System_Daemon за някои полезни инструменти, ако се интересуват от този подход.

Едно нещо, което трябва да имате предвид, е колко искате да внимавате за случайно двойно изпращане на този имейл. Ако изпълнявате този код само в една нишка, това е доста лесно, но ако някога искате да изградите до точката, в която имате няколко различни разпределени машини, които създават и изпращат тези имейли, трябва да сте малко по-внимателни. Ако го изпълнявате от cron, можете ли да гарантирате, че едно изпълнение винаги ще бъде завършено, преди да започне друго?

person FoolishSeth    schedule 28.02.2013