【问题标题】:Why should I build an API with an asynchronous/non-blocking framework?为什么要使用异步/非阻塞框架构建 API?
【发布时间】:2015-03-09 00:31:48
【问题描述】:

我一直在研究 Play Framework 作为帮助我构建简单 API 的可能候选者。但是,Django Rest Framework (DRF) 似乎也是一个非常强大的内容。

据我所知,DRF 并不像 Play 框架那样宣传自己是一个异步(或非阻塞)框架,但我对这是否重要感兴趣。我一直在想的情况是通过 Mandrill 向用户发送电子邮件——我不希望我的 API 陷入等待 Mandrill API 告诉它是否发送了电子邮件。

因此,我认为这个问题可以总结如下:从客户的角度来看,我使用 Play over DRF 等异步/非阻塞框架构建 API 是否会带来好处,还是我错过了点?

【问题讨论】:

  • 我希望它不会太主观,因为我不是在问使用哪种框架,而是在问使用哪种类型的框架。 Play/Django 只是我的例子,如果这让你感到困扰,请随时更正标签

标签: api asynchronous playframework django-rest-framework


【解决方案1】:

我是 Django REST 框架的贡献者(和用户),所以我的观点偏向于此。

Django REST 框架建立在 Django 之上,它是一个用于 Web 应用程序的同步框架。如果您已经在使用 Django 之类的同步框架,那么拥有同步 API 问题不大

现在,仅仅因为它是同步的,并不意味着一次只能处理一个请求。大多数处理 Django 应用程序的 Web 服务器 can handle multiple requests,一些主题甚至会这样做 somewhat asynchronously across multiple threads。通常这实际上不是问题,因为您的 Web 服务器通常可以处理许多并发请求,即使其中一些是阻塞的。当你有很长的阻塞调用时,你通常不希望在 API 中完成 - 你应该将其委托给后台工作人员,如 CeleryResque

这不仅仅针对 Django,许多相同的原则也适用于其他同步框架,例如 Rails 和 ASP.NET MVC。如果您有长时间运行的请求,您通常应该将工作委派给其他进程,而不是搁置请求。 202响应码for these cases很常见。

现在,这并不一定意味着异步框架毫无用处。在 Node.js 等运行时,大多数框架 handle requests asynchronously。在这些语言中使用同步框架没有意义,因此大多数库都是异步构建的。

您选择什么很大程度上取决于您已经在使用的工具。

【讨论】:

  • 很好——这很有意义。我不太确定如何处理这些持久的过程,但你解释得很好
  • 这个答案没有解释异步/同步之间的区别。塞勒姆的回答很好地说明了这一点,应该被选为正确答案。
  • 这个答案从“这就是为什么你通常不需要担心”的角度回答了这个问题,这似乎符合提问者的需求(“我对这个问题是否感兴趣甚至很重要”)。我假设如果他们问为什么一个比另一个更好,他们通常知道主要区别是什么(阻塞与非阻塞)。
  • 对不起,我表达错了。我指的是同步/异步之间的资产和缺点,而不是差异。您的回答中还有其他问题。 Node.js 不是一种语言,而是基于 JS 语言的服务器端运行时环境。 Node.js 是完全异步的,因为它只在单个线程上运行。并且仅在单个线程上运行的非异步服务器只能同时处理一个请求。异步应用程序通常具有更高的吞吐量,因为它们需要更少的线程。因此它们可以同时处理更多的请求。
  • 我还要补充一点,ASP.NET MVC 和 WebAPI 具有完整的异步功能。
【解决方案2】:

关于连接到您的应用的客户端,无论您的服务器是否使用异步/非阻塞 (ANB) 技术,都应该没有区别。但这可能会对您的应用可以处理的请求数量产生很大影响。

假设以下场景:一个请求检查 FB/Google/etc 访问令牌是否有效,然后使用它获取用户的社交资料,然后返回一些内容。

如果您在服务器中使用阻塞式 http 客户端,则在 2 个 http 请求中的每一个期间,服务该请求的线程可能会被阻塞很多时间,什么也不做。 如果您在发出 HTTP 请求并返回响应时使用非阻塞 http 客户端(如 Play 带来的客户端),则该线程可用于执行其他操作(例如:处理另一个请求的一部分)。

请注意,要解决这个“问题”,您不需要 ANB 框架,只需要一个 ANB http 客户端。因此,您应该更多地关注您的应用程序中的操作类型,并检查您选择的框架将如何处理它们。例如:如果您的应用程序几乎包含 DB CRUD 操作并且 DB 驱动程序是阻塞的(如 Java 中的 JDBC 和可能由 Django 使用的那些),那么框架是否异步并不重要,您将阻塞大部分该特定组件的时间。

在您的电子邮件示例中,Django+Celery 可能与 Play/Akka 一样好。

【讨论】:

  • 您肯定需要一个 ANB 框架,因为您还必须以 aysnc 方式处理从 API 返回的响应。否则你的应用程序会以任何形式阻塞线程。为了保证您的应用程序完全异步,每个组件也必须是异步的。 @见reactivemanifesto.org
【解决方案3】:

非异步框架通常会执行长时间运行的任务,将它们传递给一些外部进程(例如,用于 Rails 开发的 Resque/DelayedJob/sidekiq)

只是想补充一点,Mandrill API 支持发送电子邮件的异步参数。 这是他们的文档所说的:

启用针对批量发送优化的后台发送模式。在异步模式下,messages/send 将立即为每个收件人返回“排队”状态。要在以异步模式发送时处理拒绝,请为 'reject' 事件设置 webhook。

因此,如果将 async 设置为 true,您将在执行 API 调用后立即获得处理,而无需等待发送所有电子邮件。

https://mandrillapp.com/api/docs/messages.JSON.html#method-send

(我以 JSON 版本的 API 为例)

【讨论】:

  • 啊,当然,谢谢你指点我。但我想我还不能评论非我的帖子,我只是在这里做第一步:)
【解决方案4】:

如果你愿意,Django 社区现在正在研究这个东西,你可以使用 sync_to_async() 适配器。 它有一些限制和性能损失,但社区仍在努力。

下面的链接将帮助您使用sync_to_async() 适配器

https://docs.djangoproject.com/en/3.2/topics/async/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-15
    • 2018-04-06
    • 2012-05-26
    • 1970-01-01
    相关资源
    最近更新 更多