zoukankan      html  css  js  c++  java
  • flask 使用 gevent-websocket + gunicorn 部署 (python 实时日志开发+部署)

    1 我的falsk websocket 环境 pip install -r ******.txt

    eventlet==0.24.1
    flake8==3.8.4
    Flask==0.11.1
    Flask-Cors==3.0.10
    Flask-Script==2.0.5
    Flask-SocketIO==2.7.2
    Flask-Sockets==0.2.1
    gevent==20.6.2
    gevent-websocket==0.10.1
    gpg==1.13.1
    greenlet==1.1.1
    gunicorn==19.10.0
    python-socketio==5.4.0
    websockets==8.1
    Werkzeug==1.0.0
    

    2 python 后端代码

    # -*- coding: utf-8 -*-
    from flask import Flask,request,render_template,redirect,session
    import uuid,datetime
    import subprocess
    import sys
    
    from geventwebsocket.handler import WebSocketHandler
    from gevent.pywsgi import WSGIServer
    import json,os
    
    from log.log import create_app, setup_log  # 配置日志
    from config.config import Config
    import logging
    
    from flask import Flask, views, render_template, send_file, request, session, current_app
    
    app = create_app("development")
    
    app.secret_key = ';lkjnfdidiclsjek'
    from flask_cors import CORS  # 跨域
    cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
    from flask_sockets import Sockets
    sockets = Sockets(app)
    
    
    def log_path(modle):
       
        return path_data.get(modle) # 返回日志路径
    
    
    WEBSOCKET_DICT = {}
    
    @app.route('/login',methods=['GET','POST'])
    def login():
        if request.method == 'GET':
            return render_template('login.html')
        else:
            uid = str(uuid.uuid4())
            session['user_info'] = {'id': uid, 'name': request.form.get('user')}
            return 'w'
    
    def _decode_data(byte_data: bytes):
        """
        解码数据
        :param byte_data: 待解码数据
        :return: 解码字符串
        """
        try:
            return byte_data.decode('UTF-8')
        except UnicodeDecodeError:
            return byte_data.decode('GB18030')
        
    @sockets.route('/message')
    def message(ws):
        # modle = request.args.get("modle", None)
        # print('123',modle)
        uid = str(uuid.uuid4())
        # session['user_info'] = uid
        # . 判断是否为Websocket请求,http不包含wsgi.websocket
        # ws = request.environ.get('wsgi.websocket')
        # print(ws)
        if not ws:
            return 'use websocket'
        # 此处连接成功
        print('ok',session,uid)
        # session.clear()
        current_user_id =uid # 自定义websocket发送对象
        WEBSOCKET_DICT[current_user_id] = ws
        while True:
            # print(WEBSOCKET_DICT,'WEBSOCKET_DICT.values()')
            # . 等待用户发送消息,并接受
            try:
                message = ws.receive()  # 对应的模块密码数据
                print(message,'message')
                is_t,modle=is_password(message) # 验证密码
                if not is_t:
                    print('密码错误')
                    return '密码错误'
                path=log_path(modle)
                # 关闭 mesaage = None
                if not message:
                    del WEBSOCKET_DICT[current_user_id]
                    break
    
                print("---------------")
                for u_id,conn in WEBSOCKET_DICT.items():
                    # print(conn,'conn',uid)
                    if u_id==uid:
                        # print(conn)
                        print(path,'test')# 获取模块日志路径
                        # path='/tmp/echo_stdout.log'
                        # path='D:/zhongan/framework/myframework/logs/framework.log'
                        cmd='tail -f %s'%path
                        print('33[1;32m************** START **************33[0m',cmd)
        
                        p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stderr=subprocess.PIPE,
                                                 stdout=subprocess.PIPE, universal_newlines=True, shell=True, bufsize=1)
        
                        # 实时输出
                        while True:
                            line = p.stdout.readline()
                            print(line, end='')
                            conn.send(line)  # 发送前端
        
                            if subprocess.Popen.poll(p) == 0:  # 判断子进程是否结束
                                break
        
                        return p.returncode
            except Exception as e:
                print(e)
                
    
        return '完毕'
    
    
    
    if __name__ == '__main__':
        # 如果是http请求走app使用原有的wsgi处理,如果是websocket请求走WebSocketHandler处理
        http_server = WSGIServer(('0.0.0.0',8000 ), app, handler_class=WebSocketHandler)
        http_server.serve_forever()

    3 前端代码  index.vue

    <template>
      <div>
        <!-- <span>flask返回的数据{{modle}} -->
          
        <!-- </span> -->
        
        <br />
    <div  v-for="i in new_data">
            {{ i }}
          </div>
      </div>
    </template>
    
    <script>
      export default {
        name : 'test',
        data() {
          return {
            websock: null,
            new_data:[],
            pwd:this.$route.params.pwd
          }
        },
        created() {
          this.initWebSocket();
        },
        destroyed() {
          this.websock.close() //离开路由之后断开websocket连接
        },
        methods: {
          initWebSocket(){ //初始化weosocket
            const wsuri = "ws://192.168:8000/message";
    
            this.websock = new WebSocket(wsuri);
            this.websock.onmessage = this.websocketonmessage;
            this.websock.onopen = this.websocketonopen;
            this.websock.onerror = this.websocketonerror;
            this.websock.onclose = this.websocketclose;
          },
          websocketonopen(){ //连接建立之后执行send方法发送数据
           
            this.websocketsend(this.pwd);
          },
          websocketonerror(){//连接建立失败重连
            // this.initWebSocket();
            // alert('not ok')
          },
          add(data){
              let mes_data=[]
              mes_data.push(data)
              this.new_data=mes_data
              console.log(this.new_data)
          },
          websocketonmessage(e){ //数据接收
            this.new_data.push(e.data)
            // this.add(e.data)
            console.log(e)
           
          },
          websocketsend(Data){//数据发送
            this.websock.send(Data);
          },
          websocketclose(e){  //关闭
            console.log('断开连接',e);
            alert('密码错误')
          },
        },
        mounted() {
          this.pwd=this.$route.params.pwd
        },
      }
    </script>
    

    4 部署方案 nginx 部署前端  websocket 做后端服务 (不代理方式)

    conf文件夹下  nginx 配置

    server {
            listen 8080;
            server_name ****;
            root  /usr/share/nginx/www/; # 静态文件
            location / {
                    try_files $uri $uri/ @router;
            }
            location @router {
                    rewrite ^.*$ /index.html last;
            }
    }
    

     使用 gunicorn 启动 指定用 gevent-websocket

    5 部署后端服务 环境安装完成之后  4进程   nohup 异步启动

    hohup gunicorn -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 4 -b 0.0.0.0:8000 manage:app &
    

      

      

  • 相关阅读:
    默哀STAND SILENTLY!
    用虚拟机优化Windows(update:2008.4.24)
    UE的心情指数?
    God of War III 的发售日期?
    2009/8/15应该是一个愉快的夜晚.为林肯公园中国10月演唱会做好准备
    北京2008奥运会完美谢幕!
    《The Pursuit of Happyness / 当幸福来敲门》(2006)
    2007林肯公园上海演唱会观后感(实况像片/MP3) update:2008.1.31
    2008早上好
    Active Object C++智能指针实现
  • 原文地址:https://www.cnblogs.com/zhangshijiezsj/p/15471185.html
Copyright © 2011-2022 走看看