百木园-与人分享,
就是让自己快乐。

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__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from flask_jsonrpc import JSONRPC
from flask_cors import CORS

from .settings.dev import DevConfig
from .settings.prod import ProdConfig
from .settings import redis
from .libs.log import init_log
from flask_socketio import SocketIO

config = {
\"dev\": DevConfig,
\"prod\": ProdConfig,
}

db = SQLAlchemy()

# 初始化jsonrpc模块
jsonrpc = JSONRPC(service_url=\'/api\')

async_mode = \"eventlet\"
# async_mode = None

socketio = SocketIO(logger=True, engineio_logger=True)

app = Flask(__name__, static_url_path=\"/static\", static_folder=\"../static\", template_folder=\"../templates\")

def init_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=\'*\')

# 使用终端脚本工具启动和管理flask
manager = Manager(app)

# 数据库迁移工具
# 启用数据迁移工具
Migrate(app, db)
# 添加数据迁移的命令到终端脚本工具中
manager.add_command(\'db\', MigrateCommand)

# 日志初始化
init_log(Config)

# 初始化蓝图
from .urls import init_url
init_url(app)

# 初始化json-rpc
jsonrpc.init_app(app)

# 跨域资源共享
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)

return manager

# manage.py
from application import init_app

app = init_app(\"dev\")

\"\"\"加载模型\"\"\"
from application.apps.room.models import *
from application.apps.vote.models import *

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)

return manager

但是在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__.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_jsonrpc import JSONRPC
from flask_cors import CORS

from .settings.dev import DevConfig
from .settings.prod import ProdConfig
from .settings import redis
from .libs.log import init_log
from flask_socketio import SocketIO
import eventlet
eventlet.monkey_patch()

config = {
\"dev\": DevConfig,
\"prod\": ProdConfig,
}

db = SQLAlchemy()

# 初始化jsonrpc模块
jsonrpc = JSONRPC(service_url=\'/api\')

async_mode = \"eventlet\"
# async_mode = None

socketio = SocketIO(logger=True, engineio_logger=True)

app = Flask(
__name__,
static_url_path=\"/static\",
static_folder=\"../static\",
template_folder=\"../templates\"
)

def init_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 .urls import init_url
init_url(flask_app)

# 初始化json-rpc
jsonrpc.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 manager
return flask_app

# manage.py
from application import init_app, app, socketio

app = init_app(\"dev\", app)

\"\"\"加载模型\"\"\"
from application.apps.room.models import *
from application.apps.vote.models import *

if __name__ == \'__main__\':
socketio.run(app=app, use_reloader=False)

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

来源:https://www.cnblogs.com/wylshkjj/p/15681986.html
图文来源于网络,如有侵权请联系删除。

未经允许不得转载:百木园 » Flask+flask-socketio+jsonrpc组合配置避坑

相关推荐

  • 暂无文章