【问题标题】:SendGrid for PHP is slow. Are non-blocking requests possible?PHP 的 SendGrid 很慢。非阻塞请求是否可能?
【发布时间】:2014-08-05 11:08:57
【问题描述】:

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

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

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

我的问题:

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

一如既往,非常感谢任何回复或建议。提前致谢!

【问题讨论】:

  • 您可以将电子邮件的处理移至移动应用程序。您可以利用 Obj-c 库和 Java 库进行快速集成。
  • 您好库纳尔,感谢您的回复。我们知道本机应用程序环境的库。但是,我们希望在我们的网络服务端保留所有电子邮件发送,因为我们在我们的电子邮件中使用自定义动态 A/B 测试(如果我们决定 A /B 测试一封电子邮件,因为现在我们可以在我们的 web 服务端轻松地更改它)。您是否知道使请求“非阻塞”的任何方法,这意味着它只会发送请求而不等待任何响应?有点像 AJAX / 异步请求......我想道歉,因为我在这个领域不是很有经验。
  • 在应用程序外部控制电子邮件内容(并保持应用程序电子邮件之间的一致性)的一种方法是使用the SendGrid Template Engine 来控制电子邮件内容,然后让您的应用程序告诉我们(SendGrid)您想要发送您的欢迎电子邮件(例如)

标签: php mysql sendgrid


【解决方案1】:

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

异步请求

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

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

意见土地

我们现在进入了半意见领域,但是您描述的队列(例如带有 cron 作业的 mySQL 队列、文本文件或其他东西)往往具有很强的可扩展性因为如果您需要更快地处理,您可以将工作人员放在队列中。这些可以在您面向用户的系统之外(因此不共享资源)。

队列

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

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

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

排队电子邮件

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

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

【讨论】:

  • 多么棒的回复!我会花一些时间查看您提到的所有资源(segment.io 博客文章看起来也很棒)。感谢您为此付出的时间,如果这解决了我们的问题,我会尽快报告。
  • 我们决定用 PHP/mySQL 编写自己的解决方案,第一步将所有电子邮件存储在数据库中,然后工作人员将遍历数据库并逐个处理每封电子邮件。 @Nick Q。跟进问题:为了设置工作人员,我们考虑创建一个 cron 来调用每分钟处理电子邮件的 php 脚本。这是一个好的解决方案,还是有更好的方法来安排电子邮件的处理?
  • 调用 PHP 脚本的 cron 作业应该没问题,如果您自己滚动它可能是一个相当不错的解决方案。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 2013-11-12
    • 2015-08-25
    • 2021-08-28
    相关资源
    最近更新 更多