使用Flask的做服务,可以以python code.py的方式运行,但这种方式不能用于生产环境,不稳定,比如说,每隔十几分钟,有一定概率遇到连接超时无返回的情况。
我这周做了一些调研,关于python flask做服务时,处理多线程,高并发的一些手段,主要包括以下的几个方面:
1,通过设置app.run()的参数,来达到多进程的效果。看一下app.run的具体参数:
通过官方文档,可以得出,我们可以通过threaded来实现多线程的目的。通过设置processes来达到多进程的目的。
但需要注意的是threaded与processes不能同时打开,如果同时设置的话,将会出现以下的错误:
2,使用gevent做协程,从而解决高并发的问题:
具体的代码如下:
然后通过这种方式包装WSGIServer((address, port), app).serve_forever()
通过python code.py的方法,来启动服务
3,通过Gunicorn(with gevent)的形式对app进行包装,从而来启动服务。
关于Gunicorn的参数如下:可以通过Gunicorn -h来查看,下面放部分参数
通过下面的代码,来进行启动代码:
gunicorn -c gun.py thread_explore:app
其中 gun.py是gunicorn的配置文件
thread_explore是服务的主程序
app是flask的app
gun.py的具体内容如下:
其中bind是服务的地址,具体形式:“address:port"
经过查阅资料,workers的数目并不是越大越好,通常是根据服务器的cpu个数来确定的,建议的个数为:
2*cpu个数+1
针对以上的各种思路,分别对其压测:
ab -n 1000 -c 20
其中n代表请求的次数,-c指的是并发的数目
测试的结果如下:
通过以上的分析,以及查阅的资料,针对flaks的高并发状况,建议采取以下的思路:
Nginx + Gunicorn(with gevent) + Flask + scoped_session
在sqlalchemy走过的一些坑:
通常我们用 SQLAlchemy 写数据的时候要创建 Session 对象来维护数据库会话,用完了再关掉。但是这种在web大量的请求的情况下,会出现线程不安全的情况:
通过查阅sqlalchemy的官网文档,以及网上的一些帖子,可以发现,解决sqlalchemy的线程不安全问题,我们可以采用scoped_session的模式来解决。
来探究一下scoped_session到底怎么回事?
白话翻译一下就是:
通常我们在初始化 web 应用时通过scoped_session
函数对原始的Session
工厂进行处理,返回出一个ScopedSession
工厂,在每个请求来的时候就可以通过这个工厂获得一个 scoped_session 对象。
这实际上实现了一种 registry 模式,它有个中心化的 registry 来保存已经创建的 session,并在你调用ScopedSession
工厂的时候,在 registry 里面找找是不是之前已经为你创建过 session 了,如果有,就直接把这个 session 返回给你,如果没有,就创建一个新的 session,并注册到 registry 中以便你下次来要的时候给你。
这样,我们在整个请求的任意环节,都可以开开心心地随时通过工厂来获取一个 “新的”session 对象,而只要在请求处理完的时候移除这个 session 就可以了。
代码如下: