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
错误。那有什么意思?我分析了旧实现的性能,它会串行处理它,我把一半时间花在刷新上。将它分成更小的 block 并没有帮助。循环的每次迭代需要 1 秒,因此通过并行化它,假设硬件有能力,我将能够显着减少运行时间并将其扩展到更多网站。有没有办法做到这一点?我该如何解决这个问题?
我确信每个作业都是真正独立的,并且不会有任何冲突的数据库事务。一切都是插入或读取。
最佳答案
worker 应该在 run 方法中初始化 curl,而不是在构造函数中。
$ch 资源然后在可堆叠对象执行期间通过 $this->worker->ch 可用于可堆叠对象。
您遇到的错误是因为您正在将 $em 写入对象范围,它不是从 pthreads 派生的,因此不是线程安全的,因此 pthreads 尝试序列化对象以进行安全存储,但对象不是可序列化,因此您会遇到所显示的错误。
解决方法是避免设置该成员,为每个 Worker 初始化一个对象实例,我可能会存储在静态范围内以避免序列化和访问这些复杂对象时不必要的互斥开销。
关于php - 具有多线程持久化和刷新的 Doctrine Entity Manager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21362984/