• Flask+flasksocketio+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来启动

  • 相关阅读:
    领域驱动设计下系统层次结构风格(转载)
    习语
    Dynamic load of a c++ dll in C#?http://www.codecomments.com/archive29020047216328.html
    C#调用DLL文件时参数对应表
    13G编程电子书开始提供BT下载
    如何在C#中加载自己编写的动态链接库(DLL)
    Problem in calling C++ dll from C# Code
    用C++编写的基于双向链表的CPtrArray类
    C++(new and malloc0
    How to create a DLL library in C and then use it with C#
  • 原文地址:https://www.cnblogs.com/wylshkjj/p/15681986.html
Copyright © 2020-2023  润新知