SendGrid for PHP很慢。非阻塞请求是否可行?

时间:2014-08-05 11:08:57

标签: php mysql sendgrid

我们目前正在开发适用于iOS和Android的移动应用。为此,我们需要一个稳定的Web服务。

要求: - 基于PHP和MySQL,必须快速,必须可扩展

我创建了一个带有多个端点的自定义编码简单Web服务,允许将数据从应用程序传递到我们的数据库,反之亦然。

我的问题:

对于正常请求(例如,更新数据库字段或执行INSERT INTO),我的自定义编码解决方案的平均响应时间低于100毫秒(使用newrelic测量)。然而,这没有任何负载(每天低于100个用户)。当我们创建出站请求(特别是使用SendGrid PHP-Framework发送电子邮件)时,我们看到响应时间为> 1000毫秒。似乎请求是"等待"来自Sendgrid的回复。是否可以告诉脚本不要等待回复"?这不是很理想。我的想法是存储所有"待定"请求到一个单独的表,然后使用cron运行所有" pending"请求并标记为"已完成"。这是一个可行的解决方案?并且每分钟一个cron是否足以处理请求(每个电子邮件可能延迟1分钟)?

与往常一样,任何回复或建议都非常感谢。提前谢谢!

2 个答案:

答案 0 :(得分:6)

回答问题的第一部分:是的,您可以使用PHP发出异步请求,甚至忽略服务的响应。但是,正如你所说,这不是一个超级好的解决方案。

异步请求

This excellent blog post on PHP Asynchronous Requests by Segment.io得出了几个结论:

  • 您可以打开套接字并写入,如this Stack Overflow Topic所述 - 但是,它似乎实际上是阻塞且相当慢(在测试中为300毫秒)
  • 您可以写入日志文件,然后以其他方式处理(本质上是一个队列,就像您描述的那样) - 但是,这需要另一个进程来读取日志并处理它。使用文件系统可能很慢,共享文件可能会导致各种问题。
  • 您可以分叉cURL请求 - 但是,这意味着您没有等待响应,因此如果SendGrid(或其他某些服务)响应错误,您可以'抓住它并做出反应。

意见土地

我们现在正在进入半意见区域,但是您描述的队列(例如带有cron作业的mySQL,或文本文件或其他内容)往往具有很高的可扩展性因为如果你需要它更快地处理,你可以把工人扔到队列中。这些可以在面向用户的系统之外(因此不共享资源)。

队列

使用队列,您将拥有一个单独的服务,负责发送带有SendGrid的电子邮件(例如)。它会将任务从队列中拉出(例如“向Nick发送电子邮件”),然后在其上执行。

有几种方法可以实现可以处理的队列。

  • 你可以编写自己的 - 因为你似乎想继续使用PHP / mySQL,如果你这样做,你需要考虑一堆排队问题和奇怪的边缘情况。但是,您将拥有绝对的控制权,对于简单的应用程序,这可能会有效。
  • 您可以实施自托管任务队列 - Celery是分布式任务队列,øMQ (ZeroMQ)RabbitMQ也可以用作任务队列。这些都是快速和分布式的,并且已经有很多想法。您需要在系统中对它们进行基准测试,看看它们是否加快了速度。这也意味着你必须自己托管其他作品。然而,从沟通的角度来看,这可能是最快的解决方案。
  • 您可以将内容传递给托管任务队列 - IronMQAmazon SQS都是很酷的托管解决方案,这意味着您不需要将资源专用于它们,另外还有IronWorkers(例如)你可以照顾其他服务。 但是,由于您正在尝试优化对外部服务的请求,因此这可能不是此方案中的解决方案。

排队电子邮件

关于排队电子邮件的主题(特别是),这是电子邮件发件人常见的事情。与其他所有内容一样,这意味着您可以获得更好的可靠性(因为如果线路上的服务失败,您可以将其保留在队列中并重试)。

但是,通过电子邮件,有一些特定的服务用于排队消息。这些是SMTP服务器。从理论上讲,您可以设置一个服务器,如sendmail,然后set SendGrid as your "smarthost"或中继,让服务器发送到SendGrid。然后,它会排队并处理服务中断,并使用很少的附加代码发送邮件。 然而,SMTP服务器很难处理,即使它们只是转发消息。此外,SMTP甚至比HTTP更慢,以建立连接,因此可能不是你想要的,但是很高兴知道。

答案 1 :(得分:0)

另一种可能的解决方案,如果您控制自己的服务器环境,这将加快您的电子邮件发送和您的应用程序是在本地安装邮件服务器,如Postfix。然后,您配置Postfix以使用您的Sendgrid凭据,因此发送的任何电子邮件都将从您的服务器发送到sendgrid。

这不是PHP解决方案,但无需编写自己的客户解决方案。如果将Postfix设置为默认邮件服务器。然后,您可以使用php mail()函数发送电子邮件。

https://sendgrid.com/docs/Integrate/Mail_Servers/postfix.html