具有多个线程持久和刷新的Doctrine Entity Manager

时间:2014-01-26 11:52:17

标签: php multithreading symfony doctrine-orm pthreads

class Job extends \Stackable
{
    public function __construct($monitor)
    {
        $this->monitor = $monitor;
    }
    public function run()
    {
        curl_setopt($this->ch, CURLOPT_URL, $this->monitor->getIp());
        $request = json_decode(curl_exec($this->ch), true);
        //some more db transactions
        $this->em->persist
        (
            (new Attempt())
                ->setMonitor($this->monitor)
                ->setTimestamp(new \DateTime())
                ->setLatency($request['latency'])
        );
        $this->em->flush();
    }
}

class ProbeWorker extends \Worker
{
    public function __construct($em)
    {
        $this->em = $em;
        $this->ch = curl_init();
    }
    public function run()
    {
        curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
    }
}

class DogeCommand extends ContainerAwareCommand
{
    protected function configure()
    {
        $this
            ->setName('wow:doge')
            ->setDescription('such speed')
        ;
    }
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $em = $this->getContainer()->get('doctrine')->getManager();
        $monitors = $em->getRepository('WowABundle:Monitor')->findAll();
        $worker = new ProbeWorker($em);
        $worker->start();
        foreach($monitors as $monitor)
        {
            $job = new ProbeJob($monitor);
            $worker->stack($job);
        }
    }
}

这给了我一个

  [PDOException]                                     
  You cannot serialize or unserialize PDO instances 

错误。那有什么意思?我描述了旧的实现的性能,它将连续处理它,我花了一半的时间用于刷新。将它拆分成更小的块并没有帮助。循环的每次迭代需要1秒,因此通过并行化,假设硬件能够,我将能够显着减少运行时间并使其扩展到更多网站。有没有办法做到这一点?我该如何解决这个问题?

我确信每项工作都是真正独立的,并且不存在任何冲突的数据库事务。一切都是插入或阅读。

1 个答案:

答案 0 :(得分:0)

worker应该在run方法中初始化curl,而不是构造函数。

然后$ ch资源在执行期间通过$ this-> worker-> ch可用于堆叠。

您遇到的错误是因为您正在将$ em写入对象作用域,它不会从pthreads下降,因此不是线程安全的,因此pthreads会尝试序列化对象以进行安全存储,但对象不是可序列化,以便您体验到的错误。

解决方法是避免设置该成员,为每个Worker初始化对象的实例,我可能会存储在静态范围内以避免序列化以及访问这些复杂对象时互斥的不必要开销。