Web在线聊天室(12) --- 收发消息(单例模式+阻塞式队列)

websocket的理解

基于代码理解

在这里插入图片描述

客户端和服务端建立连接,就产生一个新的webSocket对象,所以不存在线程安全问题(Servlet是一个实例对象,多线程操作一个对象存在线程安全问题)

理论上的实现

异步,事件驱动,io模型的理论原理

在这里插入图片描述
从网卡拿到数据,然后系统决定数据怎么交给进程,都是io的操作,由io的模型来决定如何交付数据

websocket的实现,是基于事件驱动,异步的方式(原理叫作io多路复用)

注册一个事件后,java进程(web项目不用一直阻塞等待io数据返回)【程序该做啥就做啥,系统接收到网卡传到对应端口进程的数据,websocket某个事件发生以后,由系统调用websocket的回调函数】

我(java进程运行web项目)挂了 n 个鱼竿,都绑定铃铛(注册事件),如果有鱼上钩(事件发生),铃铛会通知我,我就再把对应鱼竿的鱼处理好(执行回调函数)

websocket协议的原理

建立连接基于http协议,(包含升级协议字段)

传输数据:基于传输层tcp,应用层websocket协议,长连接,双方都保持连接状态,双方都可以收发消息

服务器接收消息的处理方式

存在问题

服务器端onMessage方法

    @OnMessage
    public void onMessage(Session session, String message) {
   
   
        // 1.遍历保存的所有session,每个都发送消息
        MessageCenter.sendMessage(message);
        // 2.消息还要保存在数据库,
        // (1)反序列化json字符串为message对象
        Message msg = Util.deserialize(message, Message.class);
        // (2)message设置接收消息的时间
//        msg.setSendTime(new Date());
        // (3)插入数据库
        int n = MessageDao.insert(msg);

        System.out.println("接收到的消息:" + message);
    }

具体发送消息sendMessage方法

    public static void sendMessage(String message) {
   
   
        try {
   
   
            //遍历map的所有数据,然后转发到所有session对象中
            Enumeration<Session> e = clients.elements();
            while (e.hasMoreElements()) {
   
   
                Session session = e.nextElement();
                session.getBasicRemote().sendText(message);
            }
        } catch (IOException ioException) {
   
   
            ioException.printStackTrace();
        }
    }

遍历所有客户端,如果客户端数量很多,sendMessage方法长时间无法返回
|
@OnMessage注解方法无法返回(接收某个客户端消息处于长时间的处理执行上)
|
大量的接收客户端消息时,产生大量的消息堆积在服务端,服务端资源占用太多

解决方案

接收消息,发送消息的步骤,分离开(用不同的线程来处理,双方可以并发,并行的执行)

阻塞队列:用来存放消息,接收的客户端消息就放在里面(放进去时很快的)

再启动一个线程,不停的拉取队列中的消息,发送(发送和接收并发并行执行,分离)

改造方案:基于阻塞队列,将接收消息和发送消息两个操作分隔开,(异步消息处理)

目的:大量消息接收时,可以降低服务器压力,达到消峰的目的

处理消息的仓库messageCenter

把该类升级为单例模式(懒汉模式)

package org
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值