ネッティーシームレスハンドオーバのRabbitMQ、ActiveMQの、rocketmq単一のチャットチャットルーム、グループチャット機能

ファイル

ファイル

必要IdleStateHandlerハートビートチャネルが有効である、とUserAuthHandler MessageHandlerのを処理して、ログイン認証処理とメッセージ:パイプライン処理チェーンネッティーでハンドラ

protected void initChannel(SocketChannel ch) throws Exception {
    ch.pipeline().addLast(defLoopGroup,
        //编码解码器
        new HttpServerCodec(),
        //将多个消息转换成单一的消息对象
        new HttpObjectAggregator(65536),
        //支持异步发送大的码流,一般用于发送文件流
        new ChunkedWriteHandler(),
        //检测链路是否读空闲,配合心跳handler检测channel是否正常
        new IdleStateHandler(60, 0, 0),
        //处理握手和认证
        new UserAuthHandler(),
        //处理消息的发送
        new MessageHandler()
    );
}

でも、すべての着信チャネルのために、私たちは保存する必要が、その後の必要性は、大量のニュースチャンネルに依存します

public static void addChannel(Channel channel) {
        String remoteAddr = NettyUtil.parseChannelRemoteAddr(channel);
        System.out.println("addChannel:" + remoteAddr);
        if (!channel.isActive()) {
            logger.error("channel is not active, address: {}", remoteAddr);
        }
        UserInfo userInfo = new UserInfo();
        userInfo.setAddr(remoteAddr);
        userInfo.setChannel(channel);
        userInfo.setTime(System.currentTimeMillis());
        userInfos.put(channel, userInfo);
    }

ログイン後、チャネルが有効チャネルとなり、チャネルが無効の後に削除されます

public static boolean saveUser(Channel channel, String nick, String password) {
        UserInfo userInfo = userInfos.get(channel);
        if (userInfo == null) {
            return false;
        }
        if (!channel.isActive()) {
            logger.error("channel is not active, address: {}, nick: {}", userInfo.getAddr(), nick);
            return false;
        }
        // 验证用户名和密码
        if (nick == null || password == null) {
            return false;
        }
        LambdaQueryWrapper<Account> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Account::getUsername, nick).eq(Account::getPassword, password);
        Account account = accountMapperStatic.selectOne(lambdaQueryWrapper);
        if (account == null) {
            return false;
        }
        // 增加一个认证用户
        userCount.incrementAndGet();
        userInfo.setNick(nick);
        userInfo.setAuth(true);
        userInfo.setId(account.getId());
        userInfo.setUsername(account.getUsername());
        userInfo.setGroupNumber(account.getGroupNumber());
        userInfo.setTime(System.currentTimeMillis());

        // 注册该用户推送消息的通道
        offlineInfoTransmitStatic.registerPull(channel);
        return true;
    }

チャネルが閉じられると、もはやメッセージを受信しません。unregisterPull消費者情報は、クライアントがもはやアセスチャットメッセージ、オフ書き込まれません。また、書き込みロック操作下からプラスがあり、チャネルを避けるためですまた、ここで、突然閉じられたチャネルをメッセージを送信し、これはエラーにつながります。

public static void removeChannel(Channel channel) {
        try {
            logger.warn("channel will be remove, address is :{}", NettyUtil.parseChannelRemoteAddr(channel));
            //加上读写锁保证移除channel时,避免channel关闭时,还有别的线程对其操作,造成错误
            rwLock.writeLock().lock();
            channel.close();
            UserInfo userInfo = userInfos.get(channel);
            if (userInfo != null) {
                if (userInfo.isAuth()) {
                    offlineInfoTransmitStatic.unregisterPull(channel);
                    // 减去一个认证用户
                    userCount.decrementAndGet();
                }
                userInfos.remove(channel);
            }
        } finally {
            rwLock.writeLock().unlock();
        }

    }

シームレス4つのインターフェイスとして定義され、中間の保存および回送チャットメッセージを使用するこれらの四つの状態、ことなく、RabbitMQの、rocketmq、ActiveMQの間で切り替えるために。順次単一のメッセージチャット、グループチャットメッセージを送信し、クライアントがメッセージの受信を開始、クライアントがオフラインメッセージを受信しません。

public interface OfflineInfoTransmit {
    void pushP2P(Integer userId, String message);

    void pushGroup(String groupNumber, String message);

    void registerPull(Channel channel);

    void unregisterPull(Channel channel);
}

ここで、どのようにRabbitMQの、rocketmq、次のようなプロセスの中間ストアアンドフォワードチャットメッセージの1〜3種類のActiveMQの:

  1. シングルトークのモデルリファレンスモデルのスレッドプールユーザーがオンラインである場合には、チャネルを介してユーザに直接送信。ユーザがオフラインである場合、次のユーザーがメッセージミドルウェアから直接ラインにプルする場合、その後、中間貯蔵に送られます。両方のミドルウェアによって送信されたすべてのメッセージを有効にすることです。この比較の利点は、パフォーマンスが向上します
  2. グループチャットメッセージはミドルウェア、ミドルウェアアセスからクライアント・メッセージをメッセージングミドルウェアを完全に転送されます。あなたはまだ直接チャネルを介して、単一の、オンライン・ユーザーとして動作するようにお話ししたい場合は、操作は、このグループのユーザがオンラインであるかを決定するために、あまりにも面倒です
  3. あなたは、オンライン消費者を登録した場合は、ミドルウェアからのメッセージを取ります。それ以外の場合は、消費者を切断、メッセージはエンドユーザーの次の行に引っ張るために、ミドルウェアのまま。これは、オフラインメッセージを受け取る実現します。
  4. かかわらず、それは上記請求項3の処理フローに従うものミドルウェア、ミドルウェアの種類か否かの、上記の4つの方法は、シームレスに保存および回送メッセージに切り替えることができます。どちらの方法は、対応するノートを開く必要があります。

ファイル

プロジェクト住所:https://github.com/shuangyueliao/netty-chat

おすすめ

転載: www.cnblogs.com/shuangyueliao/p/11427410.html