2011-01-30 41 views
1

我有一个php脚本,我使用约1密尔。每天都会向特定的Web服务请求。php多线程,mysql

问题是,在“正常”工作流程中,脚本几乎整天工作以完成工作。 因此我工作了一个额外的组件。基本上,我开发了一个脚本,它使用多卷曲GET请求来访问主脚本,以便为每个500条记录生成一些随机tempid,最后使用POST生成所有生成的临时文件,最终生成另一个多卷曲请求。 但是,我不认为这是正确的方法,所以我希望有一些建议/解决方案可以将多线程功能添加到主脚本,而无需使用其他/外部应用程序(例如我目前使用的卷曲脚本)。 这里是主要脚本:http://pastebin.com/rUQ6pwGS

回答

1

如果你想做的话,你应该安装一个消息队列。我的首选是redis,因为它是一个“数据结构服务器,因为键可以包含字符串,散列,列表,集合和有序集合”。另外redis是极其fast

使用blpop(产生一对使用php <yourscript>的工作线程同时处理工作)侦听新消息(工作)和rpush以将新消息推送到队列中。 产卵过程是昂贵的(相对),当使用消息队列时,只能在创建过程时执行一次

如果你可以(需要重新编译PHP),我会去找phpredis,因为它是用C语言编写的扩展,比纯PHP客户端要快得多。其他PRedis也是您可以使用的非常成熟的库。

你也可以使用这个brpop/rpush作为某种锁(如果你需要的话)。这是因为:

多个客户端可以阻止相同的密钥 。他们被放入一个队列中,因此第一个服务将是 之一,开始等待更早,以 第一个BLPOP先服务的方式。

我建议你看看Simon's redis tutorial,以获得redis必须提供的绝对权力的印象。

1

这是后台进程,对不对?在这种情况下,您不应该通过Web服务器运行它。从命令行运行它,无论是作为守护进程还是作为cron作业。

我的首选项是“cron”作业,因为您可以自由重启。确保你没有更多的程序正在运行的实例(你可以通过在文件系统中锁定一个文件,在数据库中做一些原子操作来达到这个目的)。

然后你只需要开始你想要的进程数,并让它们从队列中读取工作。

通常情况下这样做是有包含列来存储谁是目前excuting一个给定的任务表中的模式:

CREATE TABLE sometasks (
    ID of some kind, 
    Other info required to do task, 
    some data we need to know if the task is due yet or complete, 
    locked_by_host VARCHAR(64) NULL, 
    locked_by_pid INT NULL 
) 

然后,该过程将执行以下操作pseduo查询锁定一组任务(是的batch_size多少每批,可以是1)

UPDATE sometasks SET locked_by_host=my_hostname, locked_by_pid=my_pid 
    WHERE not_done_already AND locked_by_host IS NULL ORDER BY ID LIMIT batch_size 

然后选择行背出使用中可以找到当前进程的任务。然后处理这些任务,并将它们更新为“完成”并清除锁定。

我会选择与启动n个子流程和监控他们一个控制器进程cron作业。子进程可以定期死亡(记得PHP没有好的GC,所以它可以很容易泄漏内存),并可以重生,以防止资源泄漏。

如果工作全部完成,家长可能会退出,并等待由cron(接下来的一个小时或东西)来重生。

NB:locked_by_host可存储的主机名(PID不是在不同的主机是唯一的),允许分布式处理,但也许你并不需要的是,这样你就可以忽略它。

您可以通过把一个locked_time列,当一个任务已花费的时间太长检测这样的设计更强大的 - 你可以提醒,杀进程,并重试,或什么的。