SendGrid for PHP运行速度很慢。非阻塞请求可能吗?
我们目前正在开发一款适用于iOS和Android的移动应用。为此,我们需要一个稳定的Web服务。
要求:-基于PHP和MySQL,必须快速、可伸缩
我已经创建了一个具有多个终结点的自定义编码的简单Web服务,以允许将数据从应用程序传递到我们的数据库,反之亦然。
我的问题:
使用我的定制编码解决方案,对于普通请求(例如,更新数据库字段或执行INSERT TO),我们的平均响应时间低于100ms(使用newrelc测量)。然而,这是没有任何负载的(每天不到100个用户)。当我们创建出站请求时(具体地说,使用SendGrid PHP-框架发送电子邮件),我们看到响应时间>1000ms。看起来该请求正在"等待"来自SendGrid的响应。有没有可能告诉脚本不要"等待响应"?这真的不是很理想。我的想法是将所有"挂起"的请求存储到一个单独的表中,然后使用cron来运行所有"挂起"的请求并将它们标记为"已完成"。这是一个可行的解决方案吗?每分钟一个cron是否足够处理请求(每个电子邮件可能延迟1分钟)?一如既往,我们非常感谢您的回复或建议。提前感谢!
php
要回答问题的第一部分:<推荐答案>可以使用php进行异步请求,甚至可以忽略服务的响应。然而,正如您所说的那样,这不是一个非常好的解决方案。
异步请求
This excellent blog post on PHP Asynchronous Requests by Segment.io得出几个结论:
- 您可以打开套接字并向其写入,如this Stack Overflow Topic-所述。但是,这似乎实际上是阻塞的,并且相当慢(在他们的测试中为300ms)。
- 您可以写入日志文件,然后以另一种方式处理它(就像您描述的那样,本质上是一个队列)-但是,这需要另一个进程来读取日志并处理它。使用文件系统可能会很慢,并且共享文件可能会导致各种问题。
- 您可以派生cURL请求-但是,这意味着您不是在等待响应,所以如果SendGrid(或其他服务)响应错误,您将无法捕获它并做出反应。
意见地
我们现在正在进入半意见领域,但您所描述的队列(例如具有cron作业、文本文件或其他内容的MySQL One)往往具有很强的可伸缩性,因为如果您需要更快地处理队列,您可以将Worker放在队列中。这些资源可以在您面向用户的系统之外(因此不共享资源)。
队列
有了队列,您将拥有一个单独的服务,负责通过SendGrid(例如)发送电子邮件。它会将任务从队列中拉出(例如"向Nick发送电子邮件"),然后在队列中执行。
有几种方法可以实现您可以处理的队列。
- 您可以编写您自己的-因为您似乎希望继续使用PHP/MySQL,如果您这样做,您将需要考虑一堆排队问题和奇怪的边缘情况。但是,您将拥有绝对控制权,对于简单的应用程序,这可能会起作用。
- 您可以实现自托管任务队列-Celery是分布式任务队列,øMQ (ZeroMQ)和RabbitMQ也可以作为任务队列。这些都是为了快速和分布式的,并在其中投入了大量的思想。您需要在您的系统中对它们进行基准测试,以查看它们是否会加速。这也意味着你必须自己主持更多的作品。然而,从沟通的角度来看,这很可能是最快的解决方案。
- 您可以将内容传递给托管任务队列-IronMQ和Amazon SQS都是很酷的托管解决方案,这意味着您不需要专门为它们分配资源,此外还可以使用IronWorkers(例如)你可以叫人来处理其他的服务。但是,由于您正在尝试优化对外部服务的请求,因此这可能不是此方案中的解决方案。
将电子邮件排队
关于电子邮件排队的主题(具体地说),这是电子邮件发件人常见的事情。与其他所有服务一样,这意味着您可以拥有更好的可靠性(因为如果服务失败,您可以将其保留在队列中并重试)。
然而,对于电子邮件,有一些特定的服务用于对消息进行排队。这些是SMTP服务器。理论上,您可以设置一个类似sendmail的服务器,然后设置set SendGrid as your "smarthost",或者进行中继并将服务器发送到SendGrid。然后,它对服务中断进行排队和处理,并发送邮件,几乎不需要额外的代码。但是,SMTP服务器很难处理,即使它们只是转发消息。此外,SMTP在建立连接方面甚至比HTTP更慢,因此可能不是您想要的,但知道这一点是很好的。
相关文章