gin 、sanic、flask 读取 redis 并发对比
最近想要看下go与python的性能到底有多少差异,不比不知道,差距还是蛮大的,为了方便实验,两个后台服务都访问相同的redis服务器, 简单的使用get 命令,获取一个值, 再通过json 格式返回
go 代码 使用gin 框架
| package main
import (
"context"
"fmt"
"github.com/gin-gonic/gin"
"github.com/go-redis/redis/v8"
)
var (
Redis *redis.Client
)
func InitRedis() *redis.Client {
rdb := redis.NewClient(&redis.Options{
Addr: "127.0.0.1:6379",
Password: "xxxx", // no password set
DB: 10, // use default DB
PoolSize: 10,
})
result := rdb.Ping(context.Background())
fmt.Println("redis ping:", result.Val())
if result.Val() != "PONG" {
// 连接有问题
return nil
}
return rdb
}
func indexHandler(c *gin.Context) {
name, err := Redis.Get(c, "name").Result()
if err != nil {
c.JSON(500, gin.H{
"msg": err.Error(),
})
} else {
c.JSON(200, gin.H{
"name": name,
})
}
}
func main() {
e := gin.New()
e.Use(gin.Recovery())
Redis = InitRedis()
e.GET("/", indexHandler)
e.Run(":8080")
}
|
python 代码 使用sanic 框架
| # -*- coding: utf-8 -*-
from sanic import Sanic, Request
from sanic import response
from sanic_ext import validate
from pydantic import BaseModel
import aioredis
app = Sanic("test")
async def beforestart(app: Sanic):
address = f'redis://:xxxx@127.0.0.1:6379/10'
pool = aioredis.ConnectionPool.from_url(address)
redis = aioredis.Redis(connection_pool=pool, encoding='utf-8')
app.ctx.redis = redis
@app.get("/")
async def test(r: Request):
try:
name = await r.app.ctx.redis.get("name")
return response.json({"name": name.decode()})
except:
return response.json({"name": "err"}, status=500)
app.register_listener(beforestart, "before_server_start")
if __name__ == '__main__':
app.run(host="0.0.0.0", port=8090, access_log=False, auto_reload=True)
|
压测命令为 ./wrk -t8 -c100 -d10s --latency "http://127.0.0.1:8080/"
gin 的压测结果
| 49701 requests in 10.01s, 6.49MB read
Requests/sec: 4967.20
Transfer/sec: 664.56KB
|
python 的压测结果
| 27415 requests in 10.01s, 2.85MB read
Requests/sec: 2737.51
Transfer/sec: 291.40KB
|
gin 是 sanic 的 1.7倍, 差距还是很大的
我尝试在sanic 中使用多workers来启动,但是压测结果和使用单workers 差不多。
再看看老牌的flask 性能如何?
| from flask import Flask
from flask_redis import FlaskRedis
import logging
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
app = Flask(__name__)
app.config['REDIS_URL'] = 'redis://:xxxx@127.0.0.1:6379/10'
redis_client = FlaskRedis(app)
@app.route('/')
def index():
name = redis_client.get('name')
return {"name": name.decode()}
if __name__ == '__main__':
app.run(debug=False)
|
压测结果为
| 3685 requests in 10.01s, 647.75KB read
Requests/sec: 368.14
Transfer/sec: 64.71KB
|
好低呀
我们可以使用多线程或者多进程来提高flask 的并发能力
| # 1.threaded : 多线程支持,默认为False,即不开启多线程;
app.run(threaded=True)
# 2.processes:进程数量,默认为1.
app.run(processes=True)
ps:多进程或多线程只能选择一个,不能同时开启
|
多线程的结果,比单线程稍好一些
| 4939 requests in 10.01s, 868.18KB read
Requests/sec: 493.39
Transfer/sec: 86.73KB
|
多进程的结果
| 3655 requests in 10.01s, 642.48KB read
Requests/sec: 365.22
Transfer/sec: 64.20KB
|
和单线程结果差不多
使用genvent做协程,并且使用多进程
| from flask import Flask
from flask_redis import FlaskRedis
from gevent import monkey
from gevent.pywsgi import WSGIServer
monkey.patch_all()
from multiprocessing import cpu_count, Process
import logging
log = logging.getLogger('werkzeug')
log.setLevel(logging.ERROR)
app = Flask(__name__)
app.config['REDIS_URL'] = 'redis://:xxxx@127.0.0.1:6379/10'
redis_client = FlaskRedis(app)
@app.route('/')
def index():
name = redis_client.get('name')
return {"name": name.decode()}
if __name__ == '__main__':
#app.run(debug=False, host="0.0.0.0", processes=True)
mulserver = WSGIServer(('0.0.0.0', 5000), app)
mulserver.start()
def server_forever():
mulserver.start_accepting()
mulserver._stop_event.wait()
for i in range(cpu_count()):
p = Process(target=server_forever)
p.start()
|
此时结果是flask 中最好的
| 8650 requests in 10.01s, 1.02MB read
Requests/sec: 864.09
Transfer/sec: 104.33KB
|
做张表来对比一下
框架 |
说明 |
Requests/sec |
Transfer/sec |
flask |
单线程 |
368 |
64kb |
flask |
多线程 |
493 |
86kb |
flask |
gevent 协程 |
864 |
104kb |
sanic |
单workers与多workers 数据差不多 |
2737 |
291kb |
gin |
|
4967 |
664kb |
总结
- 单纯的以qps为指标来看,go 对于 python 来说还是处于碾压状态
- flask 结合 gevent 性能上有很大的提升
- 即使flask使用了gevent,但是与sanic和gin 还是有很大的差距