项目功能-消息推送 (重点)

  • RPC和消息队列的对比
    • 如果需要服务端立即返回结果, 最好使用RPC(效率高, 不需要中转)
    • 如果不需要服务端返回结果 或者 需要减轻生产者压力, 可以使用消息队列(消费者可以执行异步任务, 减轻同一时间服务器的并发压力)

将推送消息放入消息队列中


获取用户身份

IM服务器从消息队列中获取数据

IM

- 当用户连接IM时, 取出user_id, 并进入其user_id对应的房间
- 从消息队列中取出关注通知

# 需求: 让用户id 和 sid进行绑定
# 1.获取用户id: 传递jwt
# 2.绑定用户身份
from server import sio, JWT_SECRET
from flask import Request


def _get_user_id(token):  # 取出用户id
    # 取出jwt中的数据
    from jwt_util import verify_jwt
    payload = verify_jwt(token, secret=JWT_SECRET)
    if payload:
        return payload.get('user_id')
    else:
        return None

@sio.on('connect')
def on_connect(sid, envrion):
    request = Request(envrion)
    token = request.args.get('token')
    user_id = _get_user_id(token)
    # 用户一连接im服务器, 就让其进入自己的用户id对应的房间  room="2"
    print("进入房间: %s" % user_id)
    sio.enter_room(sid, str(user_id))

@sio.on('disconnect')
def on_disconnect(sid):
    rooms = sio.rooms(sid)
    for room in rooms:  # 断开连接, 离开所有的房间
        sio.leave_room(sid, room)

web服务器

- 将关注通知放入消息队列, 消息发送给作者的user_id对应的房间

  • 细节
    • 测试 web应用必须使用生产模式,否则消息队列管理器会报错
  • RabbitMQ amqp://guest:guest@192.168.105.128:5672
上线收到通知的逻辑
1. 用户一旦连接IM, 
1> 需要让user_id和sid建立关系
2> 一旦离线就删除关系  
3> 关系可以存在redis中

2.web应用
1> 从redis中取user_id对应的sid
2> 如果能取出, 说明在线, 直接往消息队列中添加消息
3> 如果不能取出, 说明离线, 将消息保存到redis中 

3. im应用
1> 一旦建立连接, 先从redis中查询是否有消息被保存
2> 如果有,取出并发给客户端, 取出后从redis中删除数据
3> 同时还需要从消息队列中实时取出消息数据
posted @ 2019-09-01 18:58  太虚真人  阅读(1282)  评论(0编辑  收藏  举报