Flask+flask-socketio+jsonrpc组合配置避坑

📅 2026/7/10 13:07:58 👁️ 阅读次数 📝 编程学习
Flask+flask-socketio+jsonrpc组合配置避坑

Flask+flask-socketIO+jsonrpc这种组合能被我套出来也是离谱,事先声明:出现这种组合是因为本人之前对flask框架的使用仅限于flask+jsonrpc,所以导致这种情况出现,其实flask还可以加Flask-Restful实现,至于如何使用全凭读者根据业务需求自行裁决。

我之所以写这篇文章是有原因的,就是部署的时候由于配置文件会给自己埋下许多坑,百度查不到具体的解决方法,只能自己一点点摸索

一、起源

说起这个就很danTeng,刚离开北京来到成都,就职于一家四十多人的小外包公司,大部分业务是给高校和国家电网做系统,一个项目功能迭代,要实现一个聊天室功能,当时我就在想,钉钉会议,腾讯会议,这种工具不香吗?实在不行你开个直播间加个锁,本身就是一所学校里面的管理类系统,弄个无声聊天室,真是离大谱。

没办法,甲方爸爸的要求不能不做,然后任务就落到了我的头上,以前也没做过聊天室,那就各种找资料了解相关方面的知识,起初我最先想到的是tornado框架,毕竟处理高并发,自带websocket的轻量级框架,但是我后来跑去问我以前的老师,他说也可以用socketIO来实现,我听从了这个建议,然后就组合了出来Flask+flask-socketio+jsonrpc,因为里面还有不需要长连接的功能。

二、配置文件部分

初版本的全坑配置文件,一个又一个的坑,一次又一次的填,唉。。。

我把flask+flask-socketio+jsonrpc组合成下面这种__init__.py的配置文件,然后在manage.py中调用执行

init_app函数中的参数是详细的数据库和日志的配置信息参数,我以文件的方式写在config的dev和prod里面了,这些不重要。

全坑套餐配置如下(模拟的,非项目配置):

# __init__.pyfromflaskimportFlaskfromflask_sqlalchemyimportSQLAlchemyfromflask_scriptimportManagerfromflask_migrateimportMigrate,MigrateCommandfromflask_jsonrpcimportJSONRPCfromflask_corsimportCORSfrom.settings.devimportDevConfigfrom.settings.prodimportProdConfigfrom.settingsimportredisfrom.libs.logimportinit_logfromflask_socketioimportSocketIO config={"dev":DevConfig,"prod":ProdConfig,}db=SQLAlchemy()# 初始化jsonrpc模块jsonrpc=JSONRPC(service_url='/api')async_mode="eventlet"# async_mode = Nonesocketio=SocketIO(logger=True,engineio_logger=True)app=Flask(__name__,static_url_path="/static",static_folder="../static",template_folder="../templates")definit_app(configName):"""初始化函数"""# 设置配置类Config=config[configName]# 加载配置app.config.from_object(Config)# redis初始化redis.init_app(app,decode_responses=True)# 数据库初始化db.init_app(app)# 实例化socketIO对象socketio.init_app(app=app,async_mode=async_mode,cors_allowed_origins='*')# 使用终端脚本工具启动和管理flaskmanager=Manager(app)# 数据库迁移工具# 启用数据迁移工具Migrate(app,db)# 添加数据迁移的命令到终端脚本工具中manager.add_command('db',MigrateCommand)# 日志初始化init_log(Config)# 初始化蓝图from.urlsimportinit_url init_url(app)# 初始化json-rpcjsonrpc.init_app(app)# 跨域资源共享CORS(app,resources={r"/api/*":{"origins":"*"}})# 添加socketIO命令到终端脚本工具中@manager.commanddefrun():socketio.run(app=app,host='127.0.0.1',port=9000,use_reloader=False)returnmanager
# manage.pyfromapplicationimportinit_app app=init_app("dev")"""加载模型"""fromapplication.apps.room.modelsimport*fromapplication.apps.vote.modelsimport*if__name__=='__main__':app.run()

全坑套餐:

  • 此方法仅能在windows系统跑起来,而且想flask和flask-socketio都跑起来需要使用命令:python manage.py run来执行
  • 在部署的时候就遇到了大坑因为部署需要用到Gunicorn来部署,无论如何启动愣是报错不执行,后来我把:@manager.command注释了就能执行了
# 配置片段是这样的# 跨域资源共享CORS(app,resources={r"/api/*":{"origins":"*"}})# 添加socketIO命令到终端脚本工具中# @manager.command# def run():socketio.run(app=app,host='127.0.0.1',port=9000,use_reloader=False)returnmanager

但是在windows上跑会有问题

于是我便分析配置文件,查找相关文档发现

在执行 python manage.py runserver 的时候,如果命令不是flask-script的提供的其他命令的话,就会执行flask实例的run方法, 实质上,就是 Flask(__name__).run() 而flask-script就是监测有没有收到自己的命令,虽然flask-script也会代理flask的APP, 但是flask-script的对象并不等同与flask的实例,所以提供给gunicorn的还必须得是flask的app

所以改进方法去除flask-script:

这里还存在一个之前存在的坑就是eventlet这个组建的添加方法,之前未添加

# __init__.pyfromflaskimportFlaskfromflask_sqlalchemyimportSQLAlchemyfromflask_jsonrpcimportJSONRPCfromflask_corsimportCORSfrom.settings.devimportDevConfigfrom.settings.prodimportProdConfigfrom.settingsimportredisfrom.libs.logimportinit_logfromflask_socketioimportSocketIOimporteventlet eventlet.monkey_patch()config={"dev":DevConfig,"prod":ProdConfig,}db=SQLAlchemy()# 初始化jsonrpc模块jsonrpc=JSONRPC(service_url='/api')async_mode="eventlet"# async_mode = Nonesocketio=SocketIO(logger=True,engineio_logger=True)app=Flask(__name__,static_url_path="/static",static_folder="../static",template_folder="../templates")definit_app(configName,flask_app):"""初始化函数"""# 设置配置类Config=config[configName]# 加载配置flask_app.config.from_object(Config)# redis初始化redis.init_app(flask_app,decode_responses=True)# 数据库初始化db.init_app(flask_app)# 实例化socketIO对象socketio.init_app(app=flask_app,async_mode=async_mode,cors_allowed_origins='*')# 日志初始化init_log(Config)# 初始化蓝图from.urlsimportinit_url init_url(flask_app)# 初始化json-rpcjsonrpc.init_app(flask_app)# 跨域资源共享CORS(flask_app,supports_credentials=True)socketio.run(app=flask_app,host='127.0.0.1',port=9000,use_reloader=False)# return managerreturnflask_app
# manage.pyfromapplicationimportinit_app,app,socketio app=init_app("dev",app)"""加载模型"""fromapplication.apps.room.modelsimport*fromapplication.apps.vote.modelsimport*if__name__=='__main__':socketio.run(app=app,use_reloader=False)

关键就在于去除flask-script的使用,这样linux操作系统中部署的时候就能使用Gunicorn来启动