用 Python 做到每秒处理上百万次 HTTP 请求,可能吗?也许不能,但直到最近,这已成为现实。

很多公司都在为了提升程序的执行性能和降低服务器的运营成本,而放弃 Python 去选择其它编程语言,其实这样做并不是必须,因为 Python 完全可以胜任这些任务。

Python 社区最近做了大量关于性能的优化。CPython 3.6 重写了新的字典从而全面提升解析器的执行性能。由于引入更快的调用规则和字典查询缓存,CPython 3.7 甚至还要更快。

我们可以用 PyPy 的 Just-in-Time 来编译复杂的科学计算任务,NumPy 的测试套件也优化了和 C 扩展的兼容性,同时 PyPy 还计划于今年晚些时候做到和 Python 3.5 保持一致。

了解 Japronto!

Japronto 是一个全新的,为微服务量身打造的微框架。实现它的主要目标包含够快、可扩展和轻量化。的确它快的吓人,甚至远比 NodeJS 和 Go 还要快的多的多。要感谢 asyncio,让我可以同时编写同步和异步代码。

Python 的微框架(蓝色)、NodeJS 和 Go (绿色) 和 Japronto (紫色)

勘误表:用户 @heppu 提到,如果谨慎点用 Go 的 stdlib HTTP 服务器可以写出比上图的 Go 快 12% 的代码。另外 fasthttp 也是一个非常棒的 Go 服务器,同样的测试中它的性能几乎只比 Japronto 低 18%。真是太棒了!更多细节查可以看 
https://github.com/squeaky-pl/japronto/pull/12 和 
https://github.com/squeaky-pl/japronto/pull/14

我们可以看到其实 Meinheld WSGI 服务器已经和 NodeJS 和 Go 的性能差不多了。尽管它用的是阻塞式设计,但还是要比前面那四个要快的多,前面四个用的是异步的 Python 解决方案。所以,不要轻易相信别人那些关于异步系统总是比同步系统更快的说法,虽然都是并发处理的问题,但事实远不如想象的那么简单。

虽然我只是用 “Hello World” 来完成上面这个关于微框架的测试,但它清晰的展现了各种服务器框架的处理能力。

这些测试是在一台亚马逊 AWS EC2 的 c4.2xlarge 实例上完成的,它有 8 VCPUs,数据中心选在圣保罗区域,共享主机、HVM 虚拟化、普通磁盘。操作系统是 Ubuntu 16.04.1 LTS (Xenial Xerus),内核为 Linux 4.4.0–53-generic x86_64。操作系统显示的 CPU 是 Xeon® E5–2666 v3 @ 2.90GHz。Python 我用的版本是 3.6,刚从源码编译来的。

公平起见,所有程序,包括 Go,都只运行在单个处理器内核上。测试工具为 wrk,参数是 1 个线程,100 个链接和每个链接 24 个请求(累计并发 2400 次请求)。

HTTP 流水线(图片来自 Wikipedia)

HTTP 流水线在这里起着决定性的因素,因为 Japronto 用它来做执行并发请求的优化。

大多数服务器把来自客户端的流水线和非流水线请求都一视同仁,用同样的方法处理,并没有做针对性的优化。(实际上 Sanic 和 Meinheld 也是默默的把流水线请求当做非流水线来处理,这违反了 HTTP 1.1 协议)

简单来说,通过流水线技术,客户端不用等到服务器端返回,就可以在同一条 TCP 链接上继续发送后续的请求。为了保障通讯的完整性,服务器端会按照请求的顺序逐个把结果返回给客户端。

细节优化过程

当一堆小的 GET 请求被客户端以流水线打包发送过来,服务器端很可能只需要一次系统调用,读取一个 TCP 数据包就能拿到全部的请求。

系统调用,以及在内核空间到用户空间之间移动数据,相比起在进程内部移动数据,成本要高的多。这就是为什么不到万不得已,要尽可能少做系统调用的次数。

当 Japronto 收到数据并成功解析出请求序列时,它会尝试尽可能快的把这些请求执行完成,并以正确的顺序合并所有结果,然后只执行一次系统调用发送数据给客户端。实际上因为有 scatter/gather IO 这样的系统调用,合并的工作并不需要自己去完成,只不过 Japronto 暂时还没有用到这些功能。

然而事情并不总是那么完美,有时候请求需要耗费很长时间去处理,等待完成的过程增加了不必要的延迟。

当我们做优化时,有必要考虑系统调用的成本和请求的预期完成时间。

经过优化 Japronto 拿到了 1,214,440 RPS 的成绩

除了利用客户端流水线请求,和优化调用,还有一些其它可用的技术。

Japronto 几乎都是用 C 写的。包含解析器、协议、链接管理、路由、请求、应答等对象都是用 C 扩展写的。

Japronto 力图做到 Python 的懒加载,比如,协议头的字典只有在被试图请求到时才会被创建,另外一系列的对象也只有在第一次使用时才会被创建。

Japronto 使用超牛逼的 picohttpparser C 库来解析状态、协议头以及分片的 HTTP 消息体。Picohttpparser 是直接调用现代 CPU 集成的 SSE4.2 扩展文本处理指令去快速匹配 HTTP 标记的边界(那些 10 年前的老 x86_64 CPU 都有这玩意儿)。I/O 用到了超棒的 uvloop,它是一个 libuv 的封装,在最底层,它是调用 epoll 来提供异步读写通知。

Picohttpparser 依赖 SSE4.2 和 CMPESTRI x86_64 的特性做解析

Python 是有垃圾收集功能的语言,为避免不必要的增加垃圾收集器的压力,在设计高性能系统时一定要多加注意。Japronto 的内部被设计的尝试避免循环引用和尽可能少的分配、释放内存,它会预先申请一块区域来存放对象各种,同时尝试在后续请求中重用那些没有被继续引用的 Python 的对象,而不是将那些对象直接扔掉。

这些预先申请的内存的大小被固定为 4KB 的倍数。内部结构会非常小心和频繁的使用这些连续的内存区域,以减少缓存失效的可能性。

Japronto 会尽可能避免不必要的缓存间复制,只在正确的位置执行操作。比如,在处理路由时,先做 URL 解码再进行路由匹配。

Japronto 已经可靠的实现了下面这些功能:

实现 HTTP 1.x 并且支持分片上传
完整支持 HTTP 流水线
可配置是否让链接 Keep-alive
支持同步和异步视图
Master-multiworker 多任务处理
代码热加载
简单易用的路由规则

结束语

上面提到的所有技术不只适用于 Python,也同样可以被应用到其它语言,如 Ruby、JavaScript,甚至 PHP 等。

在此要感谢 Python 社区为优化性能所付出的持续投入。尤其是 Victor Stinner @VictorStinner、INADA Naoki @methane 和 Yury Selivanov @1st1 以及整个 PyPy 团队。

献给我挚爱的 Python。

原文链接:
https://blog.csdn.net/sinat_38682860/article/details/72862220


识别图中二维码,领取python全套视频资料

用 Python 实现每秒处理 120 万次 HTTP 请求的更多相关文章

  1. 使用Python抓取猫眼近10万条评论并分析

    <一出好戏>讲述人性,使用Python抓取猫眼近10万条评论并分析,一起揭秘“这出好戏”到底如何? 黄渤首次导演的电影<一出好戏>自8月10日在全国上映,至今已有10天,其主演 ...

  2. CYQ.Data 批量添加数据性能测试(每秒千、万)

    今天有网友火晋地同学进了CYQ.Data官方群了,他正在折腾了一个各大ORM性能测试的比较的软件,如下图 折腾的种类也不少: 感觉这软件折腾的不错~~~值的期待~~~ 另外,他指出CYQ.Data 在 ...

  3. [原创]K8一句话密码爆破工具{秒破10万} 支持ASP/PHP/ASPX/JSP/CFM/DIY

    工具: K8_FuckOneShell 20161224编译: VS2012  C# (.NET Framework v4.0)组织: K8搞基大队[K8team]作者: K8拉登哥哥博客: http ...

  4. CYQ.Data 批量添加数据性能测试(每秒千、万)---003

    原文地址:https://www.cnblogs.com/cyq1162/p/3216267.html 今天有网友火晋地同学进了CYQ.Data官方群了,他正在折腾了一个各大ORM性能测试的比较的软件 ...

  5. [转帖]支撑双11每秒17.5万单事务 阿里巴巴对JVM都做了些什么?

    支撑双11每秒17.5万单事务 阿里巴巴对JVM都做了些什么? https://mp.weixin.qq.com/s?__biz=MzA3OTg5NjcyMg==&mid=2661671930 ...

  6. 让Windows Server 2008 + IIS 7+ ASP.NET 支持10万个同时请求

    具体设置如下: 1. 调整IIS 7应用程序池队列长度 由原来的默认1000改为65535. IIS Manager > ApplicationPools > Advanced Setti ...

  7. 优化IIS7.5支持10万个同时请求的配置方法

    通过对IIS7的配置进行优化,调整IIS7应用池的队列长度,请求数限制,TCPIP连接数等方面,从而使WEB服务器的性能得以提升,保证WEB访问的访问流畅. IIS7.5是微软推出的最新平台IIS,性 ...

  8. [转]优化IIS7.5支持10万个同时请求的配置方法

    通过对IIS7的配置进行优化,调整IIS7应用池的队列长度,请求数限制,TCPIP连接数等方面,从而使WEB服务器的性能得以提升,保证WEB访问的访问流畅 通过对IIS7的配置进行优化,调整IIS7应 ...

  9. 让Windows Server 2008+IIS 7+ASP.NET支持10万个同时请求

    具体设置如下: 1. 调整IIS 7应用程序池队列长度 由原来的默认1000改为65535. IIS Manager > ApplicationPools >Advanced Settin ...

随机推荐

  1. 实现itoa()

    上代码之前先讲个笑话:曾经有位面试官问:“你实现过 唉踢哦诶(音) 吗”? 我第一个想到的是各种OA系统,心想那玩意不多是Java实现的吗...过一会想明白了,瞬间石化... #include < ...

  2. [gpio]Linux GPIO简单使用方式1-sysfs

    转自:http://blog.csdn.net/drivermonkey/article/details/20132241 1.1.References 1.2.GPIO Usage from a L ...

  3. elasticsearch -- 问题纪录

    报错1: [1]: max file descriptors [65535] for elasticsearch process is too low, increase to at least [6 ...

  4. 大数据(12) - Scala安装与IDE相关配置

    一  Scala简述 统计世界top100大学计算机系年级前三名,从初中开始编程,学过20多种语言,最后认为Scala最难.好了,我们开始享受这个过程把:). 二  Scala安装与配置 Scala需 ...

  5. ansible IP

    问题解决了,用IP: "{{ ansible_eth0'ipv4' }}" 而不是{{ansible_all_ipv4_addresses}} 修改了之后的playbook 如下: ...

  6. 得到application

    ServletContext application = request.getSession().getServletContext();        String basePath = (Str ...

  7. thinkphp 集成 twig模版引擎

    下载地址:https://github.com/fucongcong/ThinkPHPLevel/archive/master.zip 控制器格式为: <?php namespace Home\ ...

  8. android 编译模块

    android 编译模块 在写完.c文件之后,需要加载到android上进行测试.使用arm-linux-gcc编译,并添加到android开发板上运行失败. 由于android与linux不同,需要 ...

  9. SSH无密码验证配置

    一. 准备工作 首先要确保你的linux系统中已经安装了ssh,对于ubuntu系统一般默认只安装了ssh client,所以还需要我们手动安装ssh server: sudo apt-get ins ...

  10. css -- 运用@media实现网页自适应中的几个关键分辨率

    经常为不同分辨率设备或不同窗口大小下布局错位而头疼,可以利用@media screen实现网页布局的自适应,但是怎样兼容所有主流设备就成了问题.到底分辨率是多少的时候设置呢? 先看下面的代码,这是从b ...