5. Netty+SpringBoot实现IM服务 之 集群(Redis订阅机制实现)

系列文章目录

  1. 技术选型、简单实现
  2. 16进制数据及解决半包和粘包
  3. 拆包器与心跳检测
  4. 用户与channel绑定
  5. 通过Redis的订阅机制实现服务集群

授权登录

  • 系列文章目录
  • 一、实现Redis的订阅机制
    • 引入Jedis 的Jar包
    • 创建订阅线程
    • 接收订阅消息
    • 发送订阅消息
  • 二、测试效果
    • 启动服务端
    • 启动使用python写的客户端
    • 开始测试
  • 三、代码分享
    • 服务端代码
    • python实现的客户端


一、实现Redis的订阅机制

引入Jedis 的Jar包

为什么要使用Jedis,而不是使用springboot的redis组件呢? 因为springboot的redis组件也依赖netty,容易引发Jar包冲突。

在pom.xml文件中加入:

<dependency>
    <groupId>redis.clientsgroupId>
    <artifactId>jedisartifactId>
    <version>3.5.1version>
dependency>

创建订阅线程

/**
 * @author Mr.Guo
 * @date 2021/3/11 上午10:14
 */
public class RedisSubscriberThread implements Runnable {
    private final String[] channel;
    private static Thread thread;

    private RedisSubscriberThread(String[] channel) {
        this.channel = channel;
    }

    @Override
    public void run() {
        final RedisSubscriber subscriber = new RedisSubscriber();
        Xa87RedisPool.getResource().subscribe(subscriber, channel);
    }

    public static void start(String... channel) {
        thread = new Thread(new RedisSubscriberThread(channel));
        thread.start();
        Xa87RedisPool.getResource().sadd("xa87-im-sub-list", channel);
    }

    public static void stop(String channel) {
        Xa87RedisPool.getResource().srem("xa87-im-sub-list", channel);
    }
}

接收订阅消息

import cn.xa87.im.X;
import cn.xa87.im.packet.Xa87Packet;
import cn.xa87.im.packet.bean.SingleMsg;
import com.alibaba.fastjson.JSON;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.JedisPubSub;

/**
 * @author Mr.Guo
 * @date 2021/3/11 上午10:18
 */
@Slf4j
public class RedisSubscriber extends JedisPubSub {

    @Override
    public void onMessage(String topic, String message) {
        log.info("Topic:" + topic + ",Message:" + message);
        Xa87Packet packet = JSON.parseObject(message, Xa87Packet.class);
        SingleMsg msg = JSON.parseObject(new String(packet.getBody()), SingleMsg.class);
        String userId = msg.getToUser();
        Channel channel = X.getChannelByUserId(userId);
        if (null == channel) {
            return;
        }
        channel.writeAndFlush(packet);
    }

    @Override
    public void onPMessage(String pattern, String channel, String message) {
        System.out.println("Pattern:" + pattern + ",Channel:" + channel + ",Message:" + message);
    }

    @Override
    public void onSubscribe(String channel, int subscribedChannels) {
        System.out.println("onSubscribe---channel:" + channel + ",subscribedChannels:" + subscribedChannels);
    }

    @Override
    public void onPUnsubscribe(String pattern, int subscribedChannels) {
        System.out.println("onPUnsubscribe---pattern:" + pattern + ",subscribedChannels:" + subscribedChannels);
    }

    @Override
    public void onPSubscribe(String pattern, int subscribedChannels) {
        System.out.println("onPSubscribe---pattern:" + pattern + ",subscribedChannels:" + subscribedChannels);
    }
}

发送订阅消息

import cn.xa87.im.packet.Xa87Packet;
import com.alibaba.fastjson.JSON;

/**
 * @author Mr.Guo
 * @date 2021/3/10 下午4:47
 */
public class MessagePublisher {
    public static void pushMessage(String topic, Xa87Packet xa87Packet) {
        Xa87RedisPool.getResource().publish(topic, JSON.toJSONString(xa87Packet));
    }
}

二、测试效果

启动服务端

启动两个服务端,端口分别是18877、18878
5. Netty+SpringBoot实现IM服务 之 集群(Redis订阅机制实现)_第1张图片
5. Netty+SpringBoot实现IM服务 之 集群(Redis订阅机制实现)_第2张图片

启动使用python写的客户端

5. Netty+SpringBoot实现IM服务 之 集群(Redis订阅机制实现)_第3张图片
5. Netty+SpringBoot实现IM服务 之 集群(Redis订阅机制实现)_第4张图片

开始测试

分别登录用户a和用户b,之后用a给b发一个消息。
5. Netty+SpringBoot实现IM服务 之 集群(Redis订阅机制实现)_第5张图片
5. Netty+SpringBoot实现IM服务 之 集群(Redis订阅机制实现)_第6张图片

5. Netty+SpringBoot实现IM服务 之 集群(Redis订阅机制实现)_第7张图片
在这里插入图片描述

三、代码分享

服务端代码

代码地址

python实现的客户端

源码下载地址

你可能感兴趣的:(Xa87-IM,netty,redis,spring,boot,im)