关于分布式环境聊天系统的搭建及开发

现在前后的的聊天实现分类:
1,通过轮询的方式。
2,通过长连接的方式。
优缺点:
第一种方式实现简单,但是实现起来会有很多坑。亲身经历过的,比如轮询会造成后端服务接口压力过大,前端也会有数据拼接展示的问题。
第二种方法是比较实际且可行的方法。下面我们来详细介绍下。
技术栈:
websocket协议,java后端服务语言,小程序前端,redis缓存等技术
实现步骤:
1,具体实现我们通过websocket来实现全都后端的消息实时通知,用redis实现后端服务节点之间的消息通知,这里redis的作用相当于一个消息队列作用等价于mq。我们通过pub,sub命令实现的一个mq。
java代码:

> public class MyWebSocket {
>     //  websocket类的作用域是每个session回话,所有这里不能通过spring来托管,需要通过手动的方式来创建一个bean对象
>     private RedisService redisService = SpringBeanUtils.getBean(RedisService.class);
>     //与某个客户端的连接会话,需要通过它来给客户端发送数据
>     private Session session;
>     //用以记录用户和房间号的对应关系(sessionId,room)
>     private static HashMap<String, String> RoomForUser = new HashMap<String, String>();
>     //用以记录房间和其中用户群的对应关系(room,List<用户>)
>     public static HashMap<String, CopyOnWriteArraySet<User>> UserForRoom = new HashMap<String, CopyOnWriteArraySet<User>>();
>     //    String uuid = UUID.randomUUID().toString();
>     String uuid = "111111111";
> 
>     /**
>      * 聊天-连接建立成功
>      *
>      * @param session
>      */
>     @OnOpen
>     public void onOpen(Session session) throws IOException {
>         log.info("聊天-连接建立成功");
>         this.session = session;
>         User user = new User(session.getId(), "", this);
>         if (UserForRoom.get(uuid) == null) {
>             CopyOnWriteArraySet<User> roomUsers = new CopyOnWriteArraySet<>();
>             roomUsers.add(user);
>             UserForRoom.put(uuid, roomUsers);
>             RoomForUser.put(session.getId(), uuid);
>         } else {
>             UserForRoom.get(uuid).add(user);
>             RoomForUser.put(session.getId(), uuid);
>         }
>         Map<String, String> result = new HashMap<>();
>         result.put("type", "bing");
>         result.put("sendUser", "系统消息");
>         result.put("id", session.getId());
>         this.sendMessage(JSON.toJSONString(result));
>     }
> 
>     /**
>      * 聊天-连接关闭调用的方法
>      */
>     @OnClose
>     public void onClose() {
>         log.info("聊天-连接关闭调用的方法");
>     }
> 
>     /**
>      * 聊天-收到客户端消息后调用的方法
>      *
>      * @param message 消息内容
>      * @param session
>      */
>     @OnMessage
>     public void onMessage(String message, Session session) {
>         log.info("聊天-收到客户端消息后调用的方法-sessionid:{}", session.getId());
>         Map<String, String> result = new HashMap<>();
>         result.put("type", "msg");
>         result.put("msg", message);
>         String room = RoomForUser.get(session.getId());
>         CopyOnWriteArraySet<User> users = UserForRoom.get(room);
>         sendMessagesOther(users, JSON.toJSONString(result));
>         //  redis发送消息到其它服务器
>         redisService.pub("LENDER_TOPIC", JSONObject.fromObject(new ChatMessageVo(MAC.getMAC(),room, message)).toString());
>     }
> 
> 
> 
>     /**
>      * 聊天-连接发生错误时的调用方法
>      *
>      * @param session
>      * @param error
>      */
>     @OnError
>     public void onError(Session session, Throwable error) {
>         log.info("聊天-连接发生错误时的调用方法");
>     }
> 
>     //  发现消息
>     private void sendMessagesOther(CopyOnWriteArraySet<User> users, String message) {
>         //群发消息
>         for (User item : users) {
>             if (item.getWebSocket() != this) {
>                 try {
>                     item.getWebSocket().sendMessage(message);
>                 } catch (IOException e) {
>                     e.printStackTrace();
>                 }
>             }
>         }
>     }
> 
>     //  发信息
>     public void sendMessage(String message) throws IOException {
>         this.session.getBasicRemote().sendText(message);
>     } }

前端js的简单代码实现:

<!DOCTYPE HTML>
<html>
<head>
    <meta charset="utf-8">
    <title>chat</title>

    <script type="text/javascript">
		var ws = null;
        function WebSocketTest()
        {
            if ("WebSocket" in window)
            {
                console.log("您的浏览器支持 WebSocket!"); 
                // 打开一个 web socket
                ws = new WebSocket("ws://192.168.219.1:6011/websocket"); 
                ws.onopen = function()
                {
                    // Web Socket 已连接上,使用 send() 方法发送数据 
                    console.log("socket链接成功");
                };
            }else
            {
                // 浏览器不支持 WebSocket
                console.log("您的浏览器不支持 WebSocket!");
            }
        }
		
		//接收到消息的回调方法
		ws.onmessage = function (event) {
			console.log("接收到消息的回调方法"+event) 
		}
		
		function WebSocketSendTest()
        {
			//	发送消息
			ws.send("发送消息");
			console.log("发送消息...");
        }
		 
    </script>

</head>
<body>

<div id="sse">
    <a href="javascript:WebSocketTest()">创建 WebSocket链接</a><br>
    <a href="javascript:WebSocketSendTest()">发送消息</a><br>
    <a href="javascript:WebSocketCloseTest()">关闭链接</a><br>
</div>

</body>
</html>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值