Netty多通道多对话管理

Netty多通道多对话管理

  • 多通道:基于不同用途,服务器会建立多个socket监听,因此用户连接服务器的时候也会连接多个socket
  • 多对话:一个用户连接服务器成功则建立一个对话,如果有多个用户则可能建立多个对话
需要解决的问题有3个:
  1. 数据隔离:确保每个对话的数据都是私密的
  2. 用户身份识别:能够确定每个连接用户的身份
  3. 多通道交互:实现通道之间的交流和信息传递

数据隔离

先上结论:

  • 线程隔离(不可行):同会话读取数据会出现线程切换,这是Netty基于事件驱动的模型的特性导致的
  • 会话隔离(可行):对于单通道业务可行,但是对于多通道业务,无法实现同一用户的数据共享
  • 身份隔离(可行):适配各种业务场景,但是身份传输和管理机制相对复杂
  1. 线程隔离(不可行)
    使用ThreadLocal存储用户数据,当出现线程切换的时候,用户数据丢失
    在这里插入图片描述

  2. 会话隔离(可行)
    有两种实现方式:使用ChannelId、使用ChannelHandlerContext的属性Attribute

  • 使用ChannelId
public class YourHandler extends ChannelHandlerAdapter {
   
   
    private Map<ChannelId, YourSessionData> sessionDataMap = new ConcurrentHashMap<>();

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
   
   
        ChannelId channelId = ctx.channel().id();
        YourSessionData sessionData = sessionDataMap.computeIfAbsent(channelId, k -> new YourSessionData());
        // 使用sessionData处理数据
    }
}
  • 使用ChannelHandlerContext的属性Attribute
public class YourHandler extends ChannelHandlerAdapter {
   
   
    private AttributeKey<YourSessionData> sessionDataKey = AttributeKey.valueOf("attName");

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
   
   
        Attribute<YourSessionData> attr = ctx.attr(sessionDataKey);
        YourSessionData sessionData = attr.get();
        if (sessionData == null) {
   
   
            sessionData = new YourSessionData();
            attr.set(sessionData);
        }
        // 使用sessionData处理数据
    }
}
  1. 身份隔离(可行)
    由用户端发起身份认证获取身份ID,并将身份ID用于存储会话数据的标识。
  • 搭建用户登录服务(这里依然使用Netty,但是实际上其他任意方式实现都可行,如使用Spring搭建Http接口)
public class LoginCenterHandler extends ChannelHandlerAdapter {
   
   
    /**
     * 为了简便,用户身份信息验证过程略,并使用UUID作为用户登录id
     * 实际使用过程中需要在channelRead方法中接收用户身份信息并验证,验证通过后保存用户登录状态
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
   
   
        super.channelActive(ctx);
        UUID uuid = UUID.randomUUID();
        byte[] bytes = UUIDUtils.toBytes(uuid);//uuid转16位字节数组,过程略
        ByteBuf buf = Unpooled.wrappedBuffer(bytes);
        final ChannelFuture f = ctx.writeAndFlush(buf);
        //保存用户登录状态略
        //登录成功后关闭通道
        f.addListener(new ChannelFutureListener() {
   
   
            @Override
            public void operationComplete(ChannelFuture future) {
   
   
                assert f == future;
                ctx.close();
            }
        });
    }
}

用户身份识别

  • 在需要验证身
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值