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

系列文章目录

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


一、实现Redis的订阅机制

引入Jedis 的Jar包

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

在pom.xml文件中加入:

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.5.1</version>
</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
在这里插入图片描述
在这里插入图片描述

启动使用python写的客户端

在这里插入图片描述
在这里插入图片描述

开始测试

分别登录用户a和用户b,之后用a给b发一个消息。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

三、代码分享

服务端代码

代码地址

python实现的客户端

源码下载地址

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值