随着人工智能项目的逐渐普及,人工智能项目目前主流的开发语言仍然是python,所以使用python作为算法对外的api需求逐渐增大。那么问题来了,目前主流的python web框架主要是flask、django、fastapi等,但受限与python是一门解析语言,其运行效率整体来说并不高(同时受困于全局解释器锁GIL,无法像java的框架一样做到真正的多线程),所以异步框架的需求应声而出,那么我将通过以下测试,对比flask、sanic以及java的spring,进行一个简单的api接口测试,生成该对比文档。
Sanic 是一个基于 Python 3.5+ 的 web 框架,依托于 uvloop、asyncio 等事件循环和异步并发模块,旨在提供支持异步高并发请求的 web 服务。
我这边不做具体描述,详细可以参考下面的链接。我归类为两点:
① 支持异步高并发请求的 web 服务
② Sanic 的使用和 Flask 非常相似
③ 搭建轻量级 Restful API 微服务,服务于企业或者团队内部
④ uvloop 可以使 asyncio 更快。事实上,它至少比 nodejs、gevent 和其他 Python 异步框架要快两倍 。基于 uvloop 的 asyncio 的速度几乎接近了 Go 程序的速度。
sanic简介
ab是Apache自带的压力测试工具。ab非常实用,它不仅可以对Apache服务器进行网站访问压力测试,也可以对其它类型的服务器进行压力测试。比如Nginx、Tomcat、IIS等。
使用ab命令进行压力测试
ab命令可以查询,举一个比较常用的例子:
ab -n 100 -c 10 http://localhost:5000-n 100表示请求总数为100
-c 10表示并发用户数为10表示请求的目标URL
这行表示处理100个请求并每次同时运行10次请求。
sanic:
from sanic import Sanic
from sanic.response import text
app = Sanic("MyHelloWorldApp")
@app.get("/")
async def hello_world(request):
return text("Hello!!!")
if __name__ == '__main__':
app.run(port=5001, host='0.0.0.0',debug=False)
# 下面的代码也可以,当时为了保证代码一致性,定义好返回response的格式。但是速度都是一致的,不影响。
from sanic import Sanic
from sanic.response import json
app = Sanic("MyHelloWorldApp")
@app.get("/")
async def test(request):
return json({"hello": "world"})
if __name__ == "__main__":
app.run(port=5001, host='0.0.0.0',debug=False)
flask:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return "Hello!!!"
if __name__ == '__main__':
app.run('0.0.0.0', port=5000,debug=False)
# 下面的代码也可以,当时为了保证代码一致性,定义好返回response的格式。但是速度都是一致的,不影响。
from flask import Flask, make_response
app = Flask(__name__)
@app.route('/')
def hello_world():
# return "Hello!!!"
resp = make_response("Hello!!!")
return resp
if __name__ == '__main__':
app.run('0.0.0.0', port=5000,debug=False)
java:
java略,封装好jar包。同样的返回内容。
flask占用端口5000,Sanic占用5001,Spring占用10001
-n:即requests,用于指定压力测试总共的执行次数
-c:即concurrency,用于指定的并发数
测试命令如下,共20000次请求,并发为1000:
ab -n 20000 -c 1000 127.0.0.1:5000/ # Flask
ab -n 20000 -c 1000 127.0.0.1:5001/ # Sanic
ab -n 20000 -c 1000 127.0.0.1:10001/ # Spring
测试结果我不贴图了,内容比较多切复杂,这里收集几个较为重要的参数作为参考。结果值我是采用每次测试三次取最高值。一般每个框架第一次调用都会相对慢一些。
框架名 | Time taken for tests (压力测试消耗的总时间) | Failed requests: (失败的请求数) Complete requests: (的总次数) | Requests per second: (平均每秒的请求数) 重要参数,代表服务器的吞吐量 |
---|---|---|---|
Flask | 37.449s | 0/20000 | 534.07 |
Flask+gunicorn | 4.630s | 0/20000 | 4319.60 |
Sanic | 10.363s | 0/20000 | 1929.99 |
Spring | 3.652s | 0/20000 | 5477.01 |
看了一下上面的测试结果,会不会发现,怎么好像Sanic也没有想象中,传说中那么强,Flask只需要通过使用gunicorn作为wsgi服务器,一样可以弥补使用原生web服务的缺点。可以充分发挥服务器的性能。
经过查阅资料发现,其实是我们配置方面没有填好。首先Sanic 自带了一个 Web 服务器。在大多数情况下,推荐使用该服务器来部署Sanic 应用,然后只需要通过修改一下app.run()里面的一些参数即可提升Sanic的性能了。
"""
fast:获得最大 CPU 性能的最简单方法是使用 fast 参数。这将自动以系统最大的核心数量来创建工作线程。
access_log: 关闭输出访问日志来提升性能。
"""
app.run(port=5001, host='0.0.0.0',debug=False,access_log=False,fast=True)
ab测试信息:
Server Software:
Server Hostname: 127.0.0.1
Server Port: 5001
Document Path: /
Document Length: 17 bytes
Concurrency Level: 100
Time taken for tests: 3.214 seconds
Complete requests: 20000
Failed requests: 0
Write errors: 0
Total transferred: 2140000 bytes
HTML transferred: 340000 bytes
Requests per second: 6221.97 [#/sec] (mean)
Time per request: 16.072 [ms] (mean)
Time per request: 0.161 [ms] (mean, across all concurrent requests)
Transfer rate: 650.15 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 6 2.9 6 18
Processing: 1 10 4.1 10 42
Waiting: 1 8 3.4 8 37
Total: 1 16 5.1 17 44
Percentage of the requests served within a certain time (ms)
50% 17
66% 18
75% 19
80% 20
90% 21
95% 23
98% 25
99% 27
100% 44 (longest request)
框架名 | Time taken for tests (压力测试消耗的总时间) | Failed requests: (失败的请求数) Complete requests: (的总次数) | Requests per second: (平均每秒的请求数) 重要参数,代表服务器的吞吐量 |
---|---|---|---|
Flask | 37.449s | 0/20000 | 534.07 |
Flask+gunicorn | 4.630s | 0/20000 | 4319.60 |
Sanic(优化后) | 3.214s | 0/20000 | 6221.97 |
Spring | 3.652s | 0/20000 | 5477.01 |
通过上面的亲测,Sanic的确在性能方面,确实是不错的选择。虽然说这次测试只是单纯的一个get请求,并没有涉及到一些内部的异步任务等等(毕竟今天要测试的是框架本身,而不是从借助外部工具的角度来说,毕竟工具,你我他,都能用的。) 性能上能够跟java的框架不分伯仲,甚至是稍微领先一丢丢,也是让人觉得惊喜的。况且,Sanic可是用自己内部的web服务器,并没有通过gunicorn等。
不过Sanic的生态,还是得继续加油,在https://python.libhunt.com/,甚至连具体信息都不全,就很离谱。。 不过庆幸的是,Sanic的官网(我下面插了链接,百度搜索不了的)做的挺不错的,有很具体的案例讲解,最最最重要,有官方中文文档选择,终于不需要网页翻译了。
以上就是这次测试的全部内容,有不足的请多多指教。其实无论是语言也好,框架也好,肯定也是咸鱼白菜,各有所爱,保持热情,做喜欢做的事情,同时能做好它,足矣