Scalable, Delayed PHP Processing

后端 未结 15 880
长情又很酷
长情又很酷 2020-12-08 01:41

I\'m working on an online PHP application that has a need for delayed PHP event. Basically I need to be able to execute arbitrary PHP code x many seconds (but it could be da

相关标签:
15条回答
  • 2020-12-08 02:12

    I would just use cron to run a PHP file every so often (i.e. 5 minutes). The PHP file would check if there are any events that need to be fired within the next interval, grab the list of interval events, and sleep until the next event. Wake up, fire next event(s) in the list, sleep until the next one, repeat until done.

    You could even scale it by forking or launching another php file to actually fire the event. Then you could fire more than one event at the same time.

    0 讨论(0)
  • 2020-12-08 02:13

    I recommend also the queue strategy, but you seem to dislike using the database as queue. You've got a XMPP infrastructure, so leverage it: use a pubsub Node and post your events to this node. Pubsub can optionally be configured to store unfetched items in a persistent way.

    Your daemon process (no matter what language) can fetch all stored items at startup time and subscribe to changes to get notified about incoming actions. This way you can solve your problem in an elegant, asynchronous way.

    0 讨论(0)
  • 2020-12-08 02:15

    I think a PHP only solution will be hard(almost impossible) to implement. I came up with two solutions to your problem.

    PHP/Redis solution

    Question asked by Kendall:

    • How stable is redis:

    Redis is very stable. The developer really writes some clean C code. You should check it out on github ;). Also a lot of big sites are using redis. For example github.They had a really interesting blog post how they made github fast :). Also superfeedr uses redis. There are a lot more big companies which are using redis ;). I would advise you to google for it ;).

    • How PHP-friendly is redis:

    PHP is very PHP friendly. A lot of users are writing PHP libraries for redis. The protocol is really simple. You can debug it with telnet ;). Looking quickly predis for example has the blocking pop implemented.

    • how would i remove events:

    I think you should use something like ZRemCommand.

    Redis is an advanced key-value store. It is similar to memcached but the dataset is not volatile, and values can be strings, exactly like in memcached, but also lists, sets, and ordered sets. All this data types can be manipulated with atomic operations to push/pop elements, add/remove elements, perform server side union, intersection, difference between sets, and so forth. Redis supports different kind of sorting abilities.

    What I came up with(Pseudo-code....):

    processor.php:

    <?php
    ######----processer.php
    ######You should do something like nohup php processor.php enough times for processors to run event. 
    #$key: should be unique, but should also be used by wakeup.php
    while(true) {
        $event = blpop($key); #One of the available blocking threads will wakeup and process event
        process($event); #You should write process. This could take some time so this process could not be available
        zrem($key1, $event); #Remove event after processing it. Added this later!!!!!!
    }
    

    client.php:

    ######----client.php
    ######The user/browser I guess should generate these events.
    #$key1: should be unique.
    #$millis: when event should run
    #$event: just the event to work on.
    
    if ("add event") {
      zadd($key1, $millis, $event);
    } else if ("delete event") {
      zremove($key1, $event)
    }
    
    #Get event which has to be scheduled first
    $first = zrange($key1, 0, 0);
    
    if ($oldfirst <> $first) { #got different first event => notify wakeup.php.
        lpush($key2, $first);
    }
    
    $oldfirst = $first;
    

    wakeup.php:

    ####wakeup.php
    #### 1 time do something like nohup php wakeup.php
    #http://code.google.com/p/redis/wiki/IntroductionToRedisDataTypes => read sorted set part.
    while(true) {
        $first = zrange($key1, 0, 0);
        $event = blpop($key2, $timeoutTillFirstEvent);
    
        if ($event == nill) {
            #Blockingqueue has timedout which means event should be run by 1 of blocking threads.
            blpop($key2, $first);
        }    
    }
    

    Something along the lines of this you could also write a pretty efficient scheduler using PHP(Okay redis is C so kickass fast :)) only and it would be pretty efficient as well :). I would also like to code this solution so stayed tuned ;). I think I could write a usable prototype in a day....

    My java solution

    This morning I think I created a java program which you can use for your problem.

    1. download:

      Visit github's download page to download the jar file(with all dependencies included).

    2. install:

      java -jar schedule-broadcaster-1.0-SNAPSHOT-jar-with-dependencies-1277709762.jar

    3. Run simple PHP snippets

      1. First php -f scheduler.php
      2. Next php -f receiver.php
    4. Questions

      I created these little snippets so that hopefully you will understand how to use my program. There is also a little bit documentation in the WIKI.

    App Engine's TaskQueue

    A quick solution would be to Use Google's app engine task queue which has a reasonable free quota. After that you have to pay for what you use.

    Using this model, App Engine's Task Queue API allows you to specify tasks as HTTP Requests (both the contents of the request as its data, and the target URL of the request as its code reference). Programmatically referring to a bundled HTTP request in this fashion is sometimes called a "web hook."

    Importantly, the offline nature of the Task Queue API allows you to specify web hooks ahead of time, without waiting for their actual execution. Thus, an application might create many web hooks at once and then hand them off to App Engine; the system will then process them asynchronously in the background (by 'invoking' the HTTP request). This web hook model enables efficient parallel processing - App Engine may invoke multiple tasks, or web hooks, simultaneously.

    To summarize, the Task Queue API allows a developer to execute work in the background, asynchronously, by chunking that work into offline web hooks. The system will invoke those web hooks on the application's behalf, scheduling for optimal performance by possibly executing multiple webhooks in parallel. This model of granular units of work, based on the HTTP standard, allows App Engine to efficiently perform background processing in a way that works with any programming language or web application framework.

    0 讨论(0)
提交回复
热议问题