Flask+flask-socketio+jsonrpc组合配置避坑 Flaskflask-socketIOjsonrpc这种组合能被我套出来也是离谱事先声明出现这种组合是因为本人之前对flask框架的使用仅限于flaskjsonrpc所以导致这种情况出现其实flask还可以加Flask-Restful实现至于如何使用全凭读者根据业务需求自行裁决。我之所以写这篇文章是有原因的就是部署的时候由于配置文件会给自己埋下许多坑百度查不到具体的解决方法只能自己一点点摸索一、起源说起这个就很danTeng刚离开北京来到成都就职于一家四十多人的小外包公司大部分业务是给高校和国家电网做系统一个项目功能迭代要实现一个聊天室功能当时我就在想钉钉会议腾讯会议这种工具不香吗实在不行你开个直播间加个锁本身就是一所学校里面的管理类系统弄个无声聊天室真是离大谱。没办法甲方爸爸的要求不能不做然后任务就落到了我的头上以前也没做过聊天室那就各种找资料了解相关方面的知识起初我最先想到的是tornado框架毕竟处理高并发自带websocket的轻量级框架但是我后来跑去问我以前的老师他说也可以用socketIO来实现我听从了这个建议然后就组合了出来Flaskflask-socketiojsonrpc因为里面还有不需要长连接的功能。二、配置文件部分初版本的全坑配置文件一个又一个的坑一次又一次的填唉。。。我把flaskflask-socketiojsonrpc组合成下面这种__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,}dbSQLAlchemy()# 初始化jsonrpc模块jsonrpcJSONRPC(service_url/api)async_modeeventlet# async_mode NonesocketioSocketIO(loggerTrue,engineio_loggerTrue)appFlask(__name__,static_url_path/static,static_folder../static,template_folder../templates)definit_app(configName):初始化函数# 设置配置类Configconfig[configName]# 加载配置app.config.from_object(Config)# redis初始化redis.init_app(app,decode_responsesTrue)# 数据库初始化db.init_app(app)# 实例化socketIO对象socketio.init_app(appapp,async_modeasync_mode,cors_allowed_origins*)# 使用终端脚本工具启动和管理flaskmanagerManager(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(appapp,host127.0.0.1,port9000,use_reloaderFalse)returnmanager# manage.pyfromapplicationimportinit_app appinit_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(appapp,host127.0.0.1,port9000,use_reloaderFalse)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,}dbSQLAlchemy()# 初始化jsonrpc模块jsonrpcJSONRPC(service_url/api)async_modeeventlet# async_mode NonesocketioSocketIO(loggerTrue,engineio_loggerTrue)appFlask(__name__,static_url_path/static,static_folder../static,template_folder../templates)definit_app(configName,flask_app):初始化函数# 设置配置类Configconfig[configName]# 加载配置flask_app.config.from_object(Config)# redis初始化redis.init_app(flask_app,decode_responsesTrue)# 数据库初始化db.init_app(flask_app)# 实例化socketIO对象socketio.init_app(appflask_app,async_modeasync_mode,cors_allowed_origins*)# 日志初始化init_log(Config)# 初始化蓝图from.urlsimportinit_url init_url(flask_app)# 初始化json-rpcjsonrpc.init_app(flask_app)# 跨域资源共享CORS(flask_app,supports_credentialsTrue)socketio.run(appflask_app,host127.0.0.1,port9000,use_reloaderFalse)# return managerreturnflask_app# manage.pyfromapplicationimportinit_app,app,socketio appinit_app(dev,app)加载模型fromapplication.apps.room.modelsimport*fromapplication.apps.vote.modelsimport*if__name____main__:socketio.run(appapp,use_reloaderFalse)关键就在于去除flask-script的使用这样linux操作系统中部署的时候就能使用Gunicorn来启动