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

bash 复制代码
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,它知道是默认阻止的。

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

最大的意外是html。

bash 复制代码
<!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

bash 复制代码
@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)

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

bash 复制代码
给站名加入闪烁,提示刷新
	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 报错.

bash 复制代码
from gevent import monkey; monkey.patch_all() 

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

继续死守耗子洞口。

因为不太明白是否需要所有客户端都用websocket建立连接。就像开始说。只是总部建立一个。然后不知道怎么让客户发消息来。既然用到了redis。队列,就想也用,它的订阅吧。 接收订阅是个长期任务。

这是百度AI给的flask-soketio 接收redis的订阅 回答

bash 复制代码
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="姓名"

bash 复制代码
	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>

这样一个闪烁就做好了。

bash 复制代码
@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的脚本带到了,所有参会主机.好在能用. 其他地点人员被点名. 此处,每处都会有同名人的提醒.

有点担心,性能损失. 每个会点不过.只有几分钟的在线时间.应该不会有影响.

相关推荐
Mr_Xuhhh1 小时前
重生之我在学环境变量
linux·运维·服务器·前端·chrome·算法
木古古1811 小时前
使用chrome 访问虚拟机Apache2 的默认页面,出现了ERR_ADDRESS_UNREACHABLE这个鸟问题
前端·chrome·apache
墨鸦_Cormorant11 小时前
使用docker快速部署Nginx、Redis、MySQL、Tomcat以及制作镜像
redis·nginx·docker
一只爱撸猫的程序猿11 小时前
一个简单的Linux 服务器性能优化案例
linux·mysql·nginx
DC_BLOG15 小时前
Linux-Nginx虚拟主机
linux·运维·nginx
Stara051115 小时前
Git推送+拉去+uwsgi+Nginx服务器部署项目
git·python·mysql·nginx·gitee·github·uwsgi
徐浪老师17 小时前
深入实践 Shell 脚本编程:高效自动化操作指南
运维·chrome·自动化
oushaojun219 小时前
ubuntu中使用ffmpeg和nginx推流rtmp视频
nginx·ubuntu·ffmpeg·rtmp
ladymorgana20 小时前
【Nginx从入门到精通】05-安装部署-虚拟机不能上网简单排错
网络·nginx·智能路由器
Dklau-c1 天前
Linux下,修改环境变量的几种方法
linux·前端·chrome