翻译进度
13
分块数量
3
参与人数

使用 Python 处理每秒百万请求
1

这是一篇协同翻译的文章,你可以点击『我来翻译』按钮来参与翻译。

file

用Python能够实现每秒处理百万级请求吗?可能最近不久就可以实现。

很多公司正在从Python迁移到其他编程语言中,以便提高运行性能并节省服务器的价格,但实际上并不需要。 Python完全可以胜任这份工作。

Python社区最近在性能方面做了很多工作。 CPython 3.6通过新的字典实现提高了整体解释器的性能。 由于引入了更快的调用约定和字典查找缓存,CPython 3.7将会更快。

对于数字处理任务,您可以使用PyPy及其即时代码编译。 您还可以运行NumPy的测试套件,该测试套件现在已经改进了与C扩展的整体兼容性。 今年晚些时候,PyPy预计将达到Python 3.5的一致性。

所有这些伟大的工作都激励我在Python广泛使用的领域之一 —— 网络和微服务开发领域进行创新。

aurora 翻译于 1年前

走进 Japronto!

Japronto 是为您的微服务需求量身打造的全新微架构。 其主要目标包括快速,可扩展和轻量级。 基于asyncio,它可以让你做同步和异步编程。 它无比地快速。 甚至比 NodeJSGo 还要快。

file

Python微框架(蓝色),黑暗力量(绿色)和Japronto(紫色)

aurora 翻译于 1年前

勘误:正如@heppu指出的那样,Go语言标准库中的HTTP服务器比图中显示的要快上12%。在这个特定的基准下,Go语言中还有一个很棒的fasthttp服务器,仅比Japronto慢18%左右。太棒了,更多细节请参照https://github.com/squeaky-pl/japronto/pull/12 和 https://github.com/squeaky-pl/japronto/pull/14
file
从上图我们可以看到服从WSGI规范的Meinheld服务器也几乎达到了NodeJS和Go同样的性能。尽管它是继承了原有的阻塞设计,但与前面四个的异步Python解决方案相比,仍然有着很出色的表现。所以不要相信异步系统总是会更快的结论。它们可以支持更多的并发,可是更多的并不仅仅只是这一点。
这里我使用了一个简单的“Hello world”微基准应用来进行测试,它清楚的显示了这一系列服务端框架解决方案的开销。

10111000 翻译于 1年前

我们租赁了亚马逊在圣保罗区的一个拥有8个虚拟CPU的c4.2xlarge实例,它默认具有共享租赁,硬件虚拟化以及磁性存储等特性。这些结果都是在这个实例上获得的。这台机器上使用了Ubuntu16.04.1 LTS(Xenial Xerus)操作系统以及Linux 4.4.0--53-generic x86_64内核。操作系统报告称使用了Xeon® CPU E5--2666 v3 @ 2.90GHz 型号的CPU,我使用了刚从源码编译的Python,其版本为3.6。
公平起见,所有的进行测试的服务器(包括Go)都只跑了单进程。服务器使用wrk 进行负载测试。每个连接使用1个线程,总共100个连接和24个并发(流水线)请求(累积并行的请求为2400个)。
file

HTTP 流水线 (图片引自维基百科)

HTTP 流水线 在这里很关键,因为Japronto其中的一个优化细节就是在执行请求把其也考虑了进去。

10111000 翻译于 1年前

大多数服务器以与非流水客户端相同(译者注:短连接)的方式执行流水客户端(译者注:长连接)的请求。它们并没有尝试做一些优化。(事实上,Sanic和Meinheld会悄然的丢弃流水客户端的一些请求,虽然这是违反HTTP1.1协议的。)
简单来说,流水请求是指,在同一个TCP连接下,客户端不需要在发送后续请求时等待服务端对之前请求进行响应。为了确保传输过程中的完整性,服务端以同样的顺序来发送请求响应。

10111000 翻译于 1年前

The gory details of optimizations

When many small GET requests are pipelined together by the client, there's a high probability that they'll arrive in one TCP packet (thanks to Nagle's algorithm) on the server side, then be read back by one system call.

Doing a system call and moving data from kernel-space to user-space is a very expensive operation compared to, say, moving memory inside process space. That's why doing it's important to perform as few as necessary system calls (but no less).

When Japronto receives data and successfully parses several requests out of it, it tries to execute all the requests as fast as possible, glue responses back in correct order, then write back in one system call. In fact the kernel can aid in the gluing part, thanks to scatter/gather IO system calls, which Japronto doesn't use yet.

有 1 个译文正在审阅中...

Note that this isn't always possible, since some of the requests could take too long, and waiting for them would needlessly increase latency.

Take care when you tune heuristics, and consider the cost of system calls and the expected request completion time.

file

Japronto gives a 1,214,440 RPS median of grouped continuous data, calculated as the 50th percentile, using interpolation.

Besides delaying writes for pipelined clients, there are several other techniques that the code employs.

Japronto is written almost entirely in C. The parser, protocol, connection reaper, router, request, and response objects are written as C extensions.

Japronto tries hard to delay creation of Python counterparts of its internal structures until asked explicitly. For example, a headers dictionary won't be created until it's requested in a view. All the token boundaries are already marked before but normalization of header keys, and creation of several str objects is done when they're accessed for the first time.

Japronto relies on the excellent picohttpparser C library for parsing status line, headers, and a chunked HTTP message body. Picohttpparser directly employs text processing instructions found in modern CPUs with SSE4.2 extensions (almost any 10-year-old x86_64 CPU has it) to quickly match boundaries of HTTP tokens. The I/O is handled by the super awesome uvloop, which itself is a wrapper around libuv. At the lowest level, this is a bridge to epoll system call providing asynchronous notifications on read-write readiness.

file

Picohttpparser relies on SSE4.2 and CMPESTRI x86_64 intrinsic to do parsing

Python is a garbage collected language, so care needs to be taken when designing high performance systems so as not to needlessly increase pressure on the garbage collector. The internal design of Japronto tries to avoid reference cycles and do as few allocations/deallocations as necessary. It does this by preallocating some objects into so-called arenas. It also tries to reuse Python objects for future requests if they're no longer referenced instead of throwing them away.

All the allocations are done as multiples of 4KB. Internal structures are carefully laid out so that data used frequently together is close enough in memory, minimizing the possibility of cache misses.

Japronto tries to not copy between buffers unnecessarily, and does many operations in-place. For example, it percent-decodes the path before matching in the router process.

Open source contributors, I could use your help.

I've been working on Japronto continuously for past 3 months --- often during weekends, as well as normal work days. This was only possible due to me taking a break from my regular programmer job and putting all my effort into this project.

I think it's time to share the fruit of my labor with the community.

Currently Japronto implements a pretty solid feature set:

  • HTTP 1.x implementation with support for chunked uploads
  • Full support for HTTP pipelining
  • Keep-alive connections with configurable reaper
  • Support for synchronous and asynchronous views
  • Master-multiworker model based on forking
  • Support for code reloading on changes
  • Simple routing

I would like to look into Websockets and streaming HTTP responses asynchronously next.

There's a lot of work to be done in terms of documenting and testing. If you're interested in helping, please contact me directly on Twitter. Here's Japronto's GitHub project repository.

Also, if your company is looking for a Python developer who's a performance freak and also does DevOps, I'm open to hearing about that. I am going to consider positions worldwide.

Final words

All the techniques that I've mentioned here are not really specific to Python. They could be probably employed in other languages like Ruby, JavaScript or even PHP. I'd be interested in doing such work, too, but this sadly will not happen unless somebody can fund it.

I'd like to thank Python community for their continuous investment in performance engineering. Namely Victor Stinner @VictorStinner, INADA Naoki @methane and Yury Selivanov @1st1 and entire PyPy team.

For the love of Python.

本文章首发在 PythonCaff
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。

原文地址:https://medium.freecodecamp.org/million-...

译文地址:https://pythoncaff.com/topics/84/using-p...

参与译者:3
讨论数量: 1

站长在哪找的这些个帖子开头的图片

1年前

  • 请注意单词拼写,以及中英文排版,参考此页
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`, 更多语法请见这里 Markdown 语法
  • 支持表情,使用方法请见 Emoji 自动补全来咯,可用的 Emoji 请见 :metal: :point_right: Emoji 列表 :star: :sparkles:
  • 上传图片, 支持拖拽和剪切板黏贴上传, 格式限制 - jpg, png, gif
  • 发布框支持本地存储功能,会在内容变更时保存,「提交」按钮点击时清空
  请勿发布不友善或者负能量的内容。与人为善,比聪明更重要!