Python 真实世界Gevent和Asyncio用例

Python 真实世界Gevent和Asyncio用例,python,multithreading,concurrency,python-asyncio,gevent,Python,Multithreading,Concurrency,Python Asyncio,Gevent,在阅读了大量的网络文章后,以下是我对并发程序的理解- 在python中,如果我们有CPU绑定的任务,那么我们可以利用 多处理模块(原因GIL)。如果我们正在进行网络i/o或磁盘i/o 然后我们可以利用多线程 在此之前,我试图了解这一切背后的基本原理,这些是我对它们的看法- 多线程环境中的同步:任务在 不同的线程,但在任何其他线程上等待任何其他正在执行的任务 线 异步:单线程:任务无需等待即可开始执行 为了完成不同的任务。在给定的时间,单个任务将 执行。多线程:任务在不同的线程中执行 不等待任何任

在阅读了大量的网络文章后,以下是我对并发程序的理解-

在python中,如果我们有CPU绑定的任务,那么我们可以利用 多处理模块(原因GIL)。如果我们正在进行网络i/o或磁盘i/o 然后我们可以利用多线程

在此之前,我试图了解这一切背后的基本原理,这些是我对它们的看法-

多线程环境中的同步:任务在 不同的线程,但在任何其他线程上等待任何其他正在执行的任务 线

异步:单线程:任务无需等待即可开始执行 为了完成不同的任务。在给定的时间,单个任务将 执行。多线程:任务在不同的线程中执行 不等待任何任务,独立完成任务 处决

异步编程模型帮助我们实现并发性。 多线程环境中的异步编程模型是 实现并行性的一种方法

所以我的理解可以归结为线程、greenlet和协同程序使用asyncio库中的事件循环运行。

我们可以使用线程实现异步IO行为(如果我们不考虑线程操作系统调度、上下文切换和内存开销),那么我们就可以从这三种模式中获益

请提供一些实际和生产级别的示例,并解释为什么使用这些示例


谢谢

在我看来,围绕每一个问题的最大考虑因素是缩放配置文件。线程和多处理可根据程序可用的线程/进程数进行扩展,而异步可根据可用进程数对基于IO的工作负载进行次线性扩展

多线程

因为这个原因,我并没有看到过很多线程的使用。Uwsgi、芹菜和其他框架提供了一个基于线程的worker。线程的一些优点是:

  • 本地支持
  • 如果您知道您的工作负载是IO绑定的,那么使用线程模型以便共享单个地址空间就不那么复杂了
  • 吞吐量根据可用进程的数量进行扩展
我不推荐线程的原因如下:

  • 竞赛条件/线程安全

许多应用程序(第三方模块)不考虑这一点,可能有共享内存,并对竞争条件开放应用程序。这是值得注意的,我经常看到

多进程

Uwsgi/Cellery:)根据我的经验,这是默认的并发原语,因为并行是可能的,竞争条件、标准库支持和非GIL的可能性较小

优点:

  • 标准库原语
缺点:

  • 流程管理(即需要跟踪流程运行状况)
  • 吞吐量根据可用进程的数量进行扩展
Asyncio

Twisted、tornado和asyncio

这在web或网络框架中非常常见,因为它们的大部分工作通常是基于IO的工作负载。异步IO使单个线程能够一次处理数百个、数千个、数万个甚至一百万个:)连接。将此与fork之前的模型或基于流程的模型进行比较,后者需要一个可用于每个并发请求的流程


这样做的主要缺点是,由于异步IO框架通常是单线程的,任何CPU限制的工作负载都会阻止事件循环的向前进行,这对于node/v8等运行时来说是一个非常常见的操作问题。

IMO最大的考虑因素是扩展配置文件。线程和多处理可根据程序可用的线程/进程数进行扩展,而异步可根据可用进程数对基于IO的工作负载进行次线性扩展

多线程

因为这个原因,我并没有看到过很多线程的使用。Uwsgi、芹菜和其他框架提供了一个基于线程的worker。线程的一些优点是:

  • 本地支持
  • 如果您知道您的工作负载是IO绑定的,那么使用线程模型以便共享单个地址空间就不那么复杂了
  • 吞吐量根据可用进程的数量进行扩展
我不推荐线程的原因如下:

  • 竞赛条件/线程安全

许多应用程序(第三方模块)不考虑这一点,可能有共享内存,并对竞争条件开放应用程序。这是值得注意的,我经常看到

多进程

Uwsgi/Cellery:)根据我的经验,这是默认的并发原语,因为并行是可能的,竞争条件、标准库支持和非GIL的可能性较小

优点:

  • 标准库原语
缺点:

  • 流程管理(即需要跟踪流程运行状况)
  • 吞吐量根据可用进程的数量进行扩展
Asyncio

Twisted、tornado和asyncio

这在web或网络框架中非常常见,因为它们的大部分工作通常是基于IO的工作负载。异步IO使单个线程能够一次处理数百个、数千个、数万个甚至一百万个:)连接。将此与fork之前的模型或基于流程的模型进行比较,后者需要一个可用于每个并发请求的流程

这样做的主要缺点是,由于异步IO框架通常是单线程的,任何CPU限制的工作负载都会阻止事件循环的向前进行,这对于node/v8等运行时来说是一个非常常见的操作问题