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 &