Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/230.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 异步发送队列电子邮件的CURL太快,重复发送_Php_Email_Curl - Fatal编程技术网

Php 异步发送队列电子邮件的CURL太快,重复发送

Php 异步发送队列电子邮件的CURL太快,重复发送,php,email,curl,Php,Email,Curl,我有一个PHP脚本,可以将发件箱电子邮件保存在数据库中,以便使用CURL方法以异步模式发送,调用此函数CURL\u process\u email\u queue: function curl_process_email_queue() { $c = curl_init(); curl_setopt($c, CURLOPT_URL, ROOTURL . "queue_emails/execute.php"); curl_setopt($c, CURLOPT_SSL_VERIFYH

我有一个PHP脚本,可以将发件箱电子邮件保存在数据库中,以便使用CURL方法以异步模式发送,调用此函数
CURL\u process\u email\u queue

function curl_process_email_queue() {


  $c = curl_init();
  curl_setopt($c, CURLOPT_URL, ROOTURL . "queue_emails/execute.php");
  curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 0);
  curl_setopt($c, CURLOPT_SSL_VERIFYPEER, 0);
  curl_setopt($c, CURLOPT_FOLLOWLOCATION, true);
  curl_setopt($c, CURLOPT_HEADER, false);
  curl_setopt($c, CURLOPT_NOBODY, true);
  curl_setopt($c, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($c, CURLOPT_FRESH_CONNECT, true);

  // Timeout super fast once connected, so it goes into async.
  curl_setopt( $c, CURLOPT_TIMEOUT, 1 );

  return curl_exec( $c );

}
我的
execute.php
是:

<?php
ob_end_clean();
ignore_user_abort(true);
ob_start();
echo('Email async');
$size = ob_get_length();
header("Content-Encoding: none");
header("Content-Length: $size");
header("Connection: close");
ob_end_flush();
flush();
if (session_id()) session_write_close();
// connection is closed at this point
// start actual processing here
send_queued_emails();
问题是CURL是异步的,而且速度非常快,所以如果我的队列表中只有一封电子邮件要发送,那么它每次都会发送两次!我试着加些睡眠,但没有成功。有没有办法将选择和删除统一起来?这样我想我能成功地解决我的问题

更新:一些有用的信息:

curl\u process\u email\u队列在我的web应用程序的每个加载页面上都被调用。在脚本末尾插入要发送到数据库中的电子邮件,因此它执行2次的速度非常快,第一次执行无法在第二次执行开始之前删除记录:

function insert_email_into_queue($email) {

  try {
            $sql = "INSERT INTO email_queue_async (Email) VALUE ($email)";
            $rs = $db->prepare($sql);
            $rs->execute();

            curl_process_email_queue();

            header("Location: ./index.php");

        } catch(PDOException $e) {
            die($e);
        }

}
generic index.php:

<?php

curl_process_email_queue();

// some script
// get html structure
//...

我知道这是一个老问题,不知道这是否仍然是您的问题,但“在我的web应用程序的每个加载页面上调用curl\u process\u email\u queue”可能是一个突出的问题。那太疯狂了。如果许多人同时访问您的网站,那么不可避免地会收到多个处理队列的请求。事务无法保存您,因为该函数将能够获取已在处理的记录。相反,使用由cron触发的单个后台进程,该进程按顺序可靠地处理队列。就我个人而言,当您处理了一条消息时,我不会完全从队列中删除…相反,只需执行“软删除”-即,将该行中的字段更新为“已处理”,并将其设置为true(或1)。然后你有一个电子邮件处理的审计记录,如果有人质疑它,或者你需要寻找漏洞。还有。。。在
insert\u email\u into\u queue
中,通过调用
curl\u process\u email\u queue()
启动处理,然后立即重定向到index.php,再次调用相同的函数。因此,即使没有多个用户的问题,您也已经成功地进行了两次处理,非常接近。这很有可能比发送电子邮件和删除行的速度更快。正如我所说的,web应用程序只需将电子邮件作业写入队列中,一个单独的后台程序就可以实际处理和发送电子邮件。另外,更安全的做法是运行select查询,如
select*FROM email\u queue\u async ORDER BY ID Desc LIMIT 1
,以便插入更多行(在删除前一个之前)您至少可以保证它得到最新的一行。在某些情况下,这会略微减少重复的机会,但不会完全删除它-后台进程确实是确保这一点的唯一方法。@ADyson HI,是的,在一些测试之后,我将队列委派给独立的cron,以便轻松解决我的问题。我发现这是一个老问题呃问题,不知道这是否仍然是您的问题,但“我的web应用程序中的每个加载页面都会调用curl\u process\u email\u队列”这可能是一个突出的问题。这太疯狂了。如果许多人同时访问你的网站,那么不可避免地你会收到多个处理队列的请求。事务无法保存你,因为该函数将能够获取一条已在处理的记录。相反,由cron触发一个后台进程,该进程请注意,我个人不会在您处理消息时完全从队列中删除…相反,只需执行“软删除”-即像“已处理”一样更新该行中的字段,并将其设置为true(或1)。然后,如果有人对此提出疑问,或者您需要查找错误,您就有了处理电子邮件的审核记录。此外,在
将电子邮件插入到队列中
中,您可以通过调用
curl\u process\u email\u queue()启动处理
,然后立即重定向到index.php,它会再次调用相同的函数。因此,即使没有多个用户的问题,您也已经成功地进行了两次处理,非常接近。发生这种情况的速度很可能比发送电子邮件和删除行的速度更快。正如我所说,web应用程序只需将电子邮件作业放入队列中,一个单独的后台程序应实际处理和发送电子邮件。此外,更安全的做法是运行select查询,如
select*FROM email\u queue\u async ORDER BY ID Desc LIMIT 1
,以便在插入更多行时(在删除前一行之前)您至少可以保证它获取最新的行。在某些情况下,这会略微降低复制的机会,但不会完全删除它-后台进程是确保这一点的唯一方法。@ADyson HI,是的,在一些测试之后,我将队列委派给独立的cron以轻松解决我的问题。
<?php

curl_process_email_queue();

// some script
// get html structure
//...