当前位置: 首页 > 工具软件 > Sanic > 使用案例 >

Sanic异步框架真的这么强吗?实践中找真理

伊铭
2023-12-01

Sanic异步框架真的这么强吗?实践中找真理,通过对Sanic、Flask、Spring三个框架进行压力测试得出答案!


前言

随着人工智能项目的逐渐普及,人工智能项目目前主流的开发语言仍然是python,所以使用python作为算法对外的api需求逐渐增大。那么问题来了,目前主流的python web框架主要是flask、django、fastapi等,但受限与python是一门解析语言,其运行效率整体来说并不高(同时受困于全局解释器锁GIL,无法像java的框架一样做到真正的多线程),所以异步框架的需求应声而出,那么我将通过以下测试,对比flask、sanic以及java的spring,进行一个简单的api接口测试,生成该对比文档。


一、Sanic是什么?

Sanic 是一个基于 Python 3.5+ 的 web 框架,依托于 uvloop、asyncio 等事件循环和异步并发模块,旨在提供支持异步高并发请求的 web 服务。
我这边不做具体描述,详细可以参考下面的链接。我归类为两点:
① 支持异步高并发请求的 web 服务

② Sanic 的使用和 Flask 非常相似
③ 搭建轻量级 Restful API 微服务,服务于企业或者团队内部
④ uvloop 可以使 asyncio 更快。事实上,它至少比 nodejs、gevent 和其他 Python 异步框架要快两倍 。基于 uvloop 的 asyncio 的速度几乎接近了 Go 程序的速度。
sanic简介

二、压测工具ab

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次请求。

三、测试步骤

1.代码实例:

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

 

2.测试过程

ab工具

-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: (平均每秒的请求数)
重要参数,代表服务器的吞吐量
Flask37.449s0/20000534.07
Flask+gunicorn4.630s0/200004319.60
Sanic10.363s0/200001929.99
Spring3.652s0/200005477.01

 

3.Sanic:是时候表演真正的技术了

看了一下上面的测试结果,会不会发现,怎么好像Sanic也没有想象中,传说中那么强,Flask只需要通过使用gunicorn作为wsgi服务器,一样可以弥补使用原生web服务的缺点。可以充分发挥服务器的性能。

经过查阅资料发现,其实是我们配置方面没有填好。首先Sanic 自带了一个 Web 服务器。在大多数情况下,推荐使用该服务器来部署Sanic 应用,然后只需要通过修改一下app.run()里面的一些参数即可提升Sanic的性能了。

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: (平均每秒的请求数)
重要参数,代表服务器的吞吐量
Flask37.449s0/20000534.07
Flask+gunicorn4.630s0/200004319.60
Sanic(优化后)3.214s0/200006221.97
Spring3.652s0/200005477.01

总结

通过上面的亲测,Sanic的确在性能方面,确实是不错的选择。虽然说这次测试只是单纯的一个get请求,并没有涉及到一些内部的异步任务等等(毕竟今天要测试的是框架本身,而不是从借助外部工具的角度来说,毕竟工具,你我他,都能用的。) 性能上能够跟java的框架不分伯仲,甚至是稍微领先一丢丢,也是让人觉得惊喜的。况且,Sanic可是用自己内部的web服务器,并没有通过gunicorn等。

不过Sanic的生态,还是得继续加油,在https://python.libhunt.com/,甚至连具体信息都不全,就很离谱。。 不过庆幸的是,Sanic的官网(我下面插了链接,百度搜索不了的)做的挺不错的,有很具体的案例讲解,最最最重要,有官方中文文档选择,终于不需要网页翻译了。

Sanic官网,百度搜索不了

以上就是这次测试的全部内容,有不足的请多多指教。其实无论是语言也好,框架也好,肯定也是咸鱼白菜,各有所爱,保持热情,做喜欢做的事情,同时能做好它,足矣

 类似资料: