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

Cam*_*ini 1 php mysql sendgrid

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

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

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

我的问题:

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

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

Nic*_* Q. 6

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

异步请求

这篇关于Segment.io的PHP Asynchronous Requests的优秀博客文章得出了几个结论:

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

意见土地

我们现在进入半意见区域,但是你所描述的队列(例如带有cron作业的mySQL,或文本文件或其他东西)往往具有很高的可扩展性,因为如果你可以将工作人员排到队列中需要它来加快处理速度.这些可以在面向用户的系统之外(因此不共享资源).

队列

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

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

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

排队电子邮件

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

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