Использование почты PHP в цикле заставляет пользователя ждать, пока страница не отобразится - PullRequest
2 голосов
/ 17 января 2011

У меня есть форум, где пользователи могут подписаться на определенную ветку. Когда кто-то отвечает в ветке, ответ добавляется в БД, и всем подписчикам отправляется оповещение по электронной почте до отображения страницы успеха.

К вашему сведению - я не использую функцию почты PHP, поскольку у моего хостинг-провайдера есть ограничение 500 в час. Я использую Google App Engine для отправки писем с помощью curl.

Проблема - когда число подписчиков превышает сотню или около того, пользователь должен ждать слишком долго, прежде чем отобразится страница успеха, потому что PHP должен сначала пройти через каждого подписчика. Есть ли способ обойти это, не прибегая к вставке электронных писем в БД, а затем обрабатывая их через cron?

Надеюсь, я понял, заранее спасибо за совет!

Ответы [ 6 ]

2 голосов
/ 17 января 2011

Вы можете написать свой почтовый скрипт и заставить его запускаться в фоновом режиме с помощью команды оболочки.

shell_exec("/path/to/php /path/to/send_notifications.php 'var1' 'var2' >> /path/to/alert_log/paging.log &");

Используя функцию PHP shell_exec, вы можете указать PHP запустить скрипт вфон.Параметры, которые вы видите в команде shell_exec, разделены пробелами.

  • /path/to/php - фактический путь к PHP на сервере (здесь вы можете просто использовать 'php')
  • /path/to/send_notifications.php - Путь к вашему почтовому скрипту
  • 'var1' 'var2' - $_SERVER['argv'] переменные, которые вы можете отправить в ваш скрипт, будут заключены в одинарные кавычки и через пробел после пути к вашему скрипту.
  • >> /path/to/alert_log/paging.log - Путь к файлу журнала (необязательно), все, что отражено в вашем почтовом скрипте, будет записано в этот файл
  • & - самый важный часть этого.& говорит вашему серверу запустить этот скрипт в фоновом режиме

Делая это таким образом, когда вы выполняете почтовый скрипт, пользователю, отправляющему форму, не нужно будет ждать завершения скрипта,Браузер загрузит страницу быстрее, и пользователь сможет отойти от страницы подтверждения или даже закрыть браузер, и скрипт продолжит работу до его завершения.

1 голос
/ 17 января 2011

Если вы используете php в качестве fastcgi, контролируемого php-pfm, тогда вы можете использовать функцию fastcgi_finish_request ().Это очень мощная функция.Он закроет соединение с браузером при вызове, но продолжит выполнение остальной части скрипта.

С тех пор, как я впервые обнаружил эту функцию, я использую ее и люблю.

0 голосов
/ 17 января 2011

Вам необходимо переместить отправку письма в отдельный скрипт. Один из способов сделать это - создать таблицу mail_queue. Таким образом, внутри вашего цикла вы просто записали бы строку в базу данных.

Затем в другом сценарии вы перебираете набор электронных писем из базы данных для отправки. Этот скрипт может быть запущен задачей cron, и он может просто обновить эту строку до «sent».

0 голосов
/ 17 января 2011

Я думаю, что проблема больше в вашей реализации. Отправка почты, особенно в больших количествах, лучше всего делать с разветвлением или отложенными заданиями. Идея разветвления заключается в том, что вы ставите в очередь «задания» и выполняете их позднее. Клиент не застрял в ожидании завершения процессов ...

Один из наиболее популярных проектов для PHP - gearman .

Некоторые другие преимущества этого подхода:

  1. Кэширование ошибок и автоматические повторы
  2. более быстрое обслуживание страниц
  3. вы можете писать собственные скрипты для сборки мусора и т.д ...
0 голосов
/ 17 января 2011

Я не думаю, что вы не должны использовать cron или что-то еще, но вы должны использовать очередь задач , чтобы выполнять обработку в автономном режиме!

Приложения App Engine могут выполнять фоновую обработку, вставляя задачи (смоделированные как веб-хуки) в очередь.App Engine обнаружит наличие новых, готовых к выполнению задач и автоматически отправит их для выполнения в соответствии с критериями планирования.

В веб-крюке (очереди задач) вы можете сделать асинхронная загрузка на ваш веб-сервис, и этот способ вызова будет сделан асинхронным, что гарантирует, что вашему пользователю не придется ждать его завершения.Я надеюсь, что вы понимаете мое решение.

0 голосов
/ 17 января 2011

Нет, процесс PHP не завершится, пока не будут выполнены все вызовы API для GAE.Однако вы можете отправлять обновления статуса пользователю во время выполнения сценария:

// in loop
// sent one message

echo "Sent email to user $email_user \n";
ob_flush();

ob_flush() заставит Apache отправить текущий буфер клиенту.В качестве альтернативы вы можете показать почтовую страницу в отдельном <div> и вызвать почтовый скрипт через ajax.

Редактировать: Я полагаю, что возможно отправлять сообщения партиями в GAE?Какая система находится на стороне GAE (Python / Java)?

...