flask 使用 gevent-websocket + gunicorn 部署 (python 实时日志开发+部署)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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 后端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# -*- 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('\033[1;32m************** START **************\033[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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
<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 配置

1
2
3
4
5
6
7
8
9
10
11
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 异步启动

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

  

 

 

 

 

 

 

 

 

 

 

 

  

 

posted @   睁yan-ii  阅读(1052)  评论(0编辑  收藏  举报
编辑推荐:
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
· 程序员常用高效实用工具推荐,办公效率提升利器!
历史上的今天:
2020-10-27 ant-design 基础格式
2020-10-27 qq获取验证码接口
2020-10-27 【Django】django.core.exceptions.ImproperlyConfigured: mysqlclient 1.4.0 or newer is required;
2020-10-27 redis 存储验证码 基本使用
点击右上角即可分享
微信分享提示