当前位置: 首页 > article >正文

flask-socketio-+Nginx反向代理在会议点名上的用作消息收发和提醒

配置
nginx
让socket.io 顺利走到后方,因为 这个 io只认一级目录,socket.io
但是的 server 是由path 参数可做设定的. 我觉他client也能吧.只是二级目录有点太绕.不去试了
1.1.1.30 :9000 nginx转到
1.1.1.25:7005 socketio, app


http {
    # 基本HTTP服务器配置
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }
 
    server {

        listen 9000;   
 location /socket.io  {
      
        proxy_http_version 1.1;
        proxy_buffering off;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
            proxy_pass http://1.1.1.25:7005/socket.io;
}

其次必须让 socketio开跨域访问,因为,中间有代理nginx,它知道是默认阻止的。

 
socketio = SocketIO(app,cors_allowed_origins="*" ,message_queue= app.config['REDIS_URL']) 
* 号可以是上面nginx在所在地址
 
 

最大的意外是html。

<!DOCTYPE html>
<html>
<head>
 <meta charset="UTF-8">
    <title>Flask-SocketIO 示例</title>
    <script type="text/javascript" src="/js/socket.io.min.js"></script>
    <script type="text/javascript" charset="utf-8">
        var socket = io.connect('http://1.1.1.30:9000/chat'  );
        socket.on('my event', function (data) {
          //  console.log('服务器发送:', data);
         
        //    socket.emit('mess', '用户已连接');
          //     alert('服务器发送:');

虽然 var socket = io.connect(‘http://1.1.1.25:9000/chat’ ); 建立连接是代理走代理。但这个地址被代理阻止的,如果是url,因为nginx开了认证,。但是websocket不吃认证这一天. 而且表面是http,却是后扩展的,用法如同socket
转为 1.1.1.30:9000/socket.io ,去询问server chat是哪位.
根据/chat.得到下面的处理handle

@socketio.on('mess' ,namespace='/chat')
def handle_mess(message):
   socketio.emit('mess', {'data': message}, namespace='/chat')
@socketio.on('message' ,namespace='/chat')
def handle_message(message):
    socketio.emit('message', {'data': '左右!'}, namespace='/chat')
    print(message+"from where......")
    
if __name__ == '__main__':
   # app.run(debug=True,host="0.0.0.0",port=5005)

这样在原有点名后台基础上,加入了在线会话提醒的功能。避免 了反复刷新架构。

给站名加入闪烁,提示刷新
	function blink(abc) {{
    $($('span:contains("'+abc+'")')[0]).fadeOut(500).fadeIn(500, blink.bind(null,abc));}}

	</script>

我也只是又一次瞎猫碰到了死耗子
这里没说我的问题,只是说了最后的设计。我的问题是,所有功能在一个,二级目录下。因为static是nginx的。而flask,是 /api下的。 nginx始终只有一个端口号来的。这让我想用 、/api/chat这样的结构。做为 io.connect(‘http://1.1.1.30:9000/api/chat’ ); 而这中间,隔了 ,一个nginx代理片段。一个app的跨域请求要求。
在突然两个都满足的时候。转了一圈通信建立了。

那么说会redis。 我的所有会议机,可以用websocket请求。但是,我是没有那么大需要。因为我没有回送数据的需要。 只有各点的提交信息,需要我去及时看。而不是一次刷新全部站点。
所以,我在提交数据时给,redis队列一个消息。在得到消息后,通过socketio给中央的控制。提醒收到一个新消息。
而且,在开通gevent,第一次使用 redis 做它的队列的时候要求,在app的开头加入

在linux 启用 redis队列后.gevent 报错.

from gevent import monkey; monkey.patch_all() 

感觉这个效果并不是太好。但是能用。

继续死守耗子洞口。
因为不太明白是否需要所有客户端都用websocket建立连接。就像开始说。只是总部建立一个。然后不知道怎么让客户发消息来。既然用到了redis。队列,就想也用,它的订阅吧。 接收订阅是个长期任务。
这是百度AI给的flask-soketio 接收redis的订阅 回答

from flask import Flask, render_template
from flask_socketio import SocketIO
import redis
 
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app)
 
@app.route('/')
def index():
    return render_template('index.html')
 
def subscribe_redis(redis_host, redis_port, redis_channel):
    r = redis.StrictRedis(host=redis_host, port=redis_port)
    pubsub = r.pubsub()
    pubsub.subscribe(**{redis_channel: on_message})
    pubsub.run_in_thread(sleep_time=0.01)
 
def on_message(message):
    data = message['data']
    socketio.emit('redis_message', data, namespace='/socketio')
 
if __name__ == '__main__':
    # 启动后台任务订阅Redis
    socketio.start_background_task(
        subscribe_redis,
        redis_host='localhost',
        redis_port=6379,
        redis_channel='my_channel'
    )
    socketio.run(app, debug=True)

确实不执行。提示socket已关闭。IO不对。然后。我一直在试。直接在python shell 中,subscribe_redis这个函数不阻塞,直接生效。 不错,好用。然而在 flask socket 包装下。一定会出错。 换来换用了一个Threading的另一个订阅方式。还是会出错,几乎一样。切换了python版本。照样。其他功能不受影响。 甚至订阅都是正常的。就是无法放在一起。

接着测试第二个方案。直接给redis中加入 flash-socketio格式的消息。 又得到AI的一个回答,说是 socketio dumps一下,消息的字典。说的没错,但是,人家大人是没有这个字典的。 我觉得经过反编码,是能找到方式的。 但是折腾了一夜。心灰了,dir(socketio)看到了。emit 、提交消息的函数。

既然整个app文件,socketip随便用,拿来发送消息就行了。于是每个点到人名的提交url中。都会发一个人名消息给中心这里。是通过websocket提交的。是即时的。
这样只有一个页面会连接到websocket 。会有消息但不是最终状态。知道一个大概。前期页面第个人名都是<a href id=“姓名”

	function blink(abc) {{
    $(abc).fadeOut(500).fadeIn(500, blink.bind(null,abc));}}

  var socket = io.connect('http://1.1.1.30:9000/chat'  );
    socket.on('mess', function(msg) {
    blink('#'+msg.data)
    })

	</script>

这样一个闪烁就做好了。

@app.route("/docheck/<sta>/<person>")
def check(sta,person):
    r=cl.sadd(f"check:{sta}",person)
    socketio.emit('mess', {'data': person}, namespace='/chat')

效率和优美就诞生了。

由于意外
lfask人的接口文件, main,和 sta,混用. 把socketio的脚本带到了,所有参会主机.好在能用. 其他地点人员被点名. 此处,每处都会有同名人的提醒.
有点担心,性能损失. 每个会点不过.只有几分钟的在线时间.应该不会有影响.


http://www.kler.cn/news/358775.html

相关文章:

  • asp.net Core 自定义中间件
  • 人工智能和机器学习之线性代数(二)
  • Java进阶——数据结构与算法之栈与递归小结(三)
  • 等保测评和等保认证有什么区别
  • Bayes-CNN-LSTM|基于贝叶斯优化的卷积-长短期神经网络多输入数据回归预测
  • 基于静态编译构建微服务应用
  • 【Docker】Docker (Dockerfile)的数据管理和网络通信
  • FPGA实现PCIE采集电脑端视频转SFP光口万兆UDP输出,基于XDMA+GTX架构,提供2套工程源码和技术支持
  • 51单片机的智能热水器控制系统【proteus仿真+程序+报告+原理图+演示视频】
  • 清空docker所有的数据
  • docker 初步理解
  • Axios 基本使用
  • 图书业务流程优化:Spring Boot进销存系统
  • 【排序】3.希尔排序法
  • 【论文速读】P-Tuning:GPT Understands, Too
  • hive_locks字段
  • 基于SpringBoot+Vue+uniapp的时间管理小程序的详细设计和实现(源码+lw+部署文档+讲解等)
  • C#/.NET/.NET Core技术前沿周刊 | 第 9 期(2024年10.07-10.13)
  • Java--集合(三)之vectorlinkedlisthashset结构
  • git通过ssh方式操作提示Permission denied (publickey). 【解决】