怎么把netty的链接通道存储到redis中这样后续可以通过key取出channel给客户端发消息
我们项目中大致是这么做的:
无论是自己写数据结构还是使用Jedis,大概都是有一个类似Map的结构。
建立一个Bean用于表示会话,此处暂且称之为Session。
在Session里引用netty的Channel。
在channelActive
时将其放入redis。
有必要的话,可以将channel.id().asLongText()
或channel.id().asShortText()
作为Session的唯一标识
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
//可以将channel.id().asLongText()或channel.id().asShortText()作为Session的ID
Session session = Session.buildSession(ctx.channel());
//Session存入Redis
pushSession2Redis(session);
logger.info("终端连接:{}", session);
}
Session.java
import java.net.SocketAddress;
import io.netty.channel.Channel;
public class Session {
//Session的唯一标识
private String id;
//和Session相关的channel,通过它向客户端回送数据
private Channel channel = null;
//上次通信时间
private long lastCommunicateTimeStamp = 0l;
//快速构建一个新的Session
public static Session buildSession(Channel channel) {
Session session = new Session();
session.setChannel(channel);
//此处暂且使用netty生成的类似UUID的字符串,来标识一个session
session.setId(channel.id().asLongText());
session.setLastCommunicateTimeStamp(System.currentTimeMillis());
return session;
}
// getter,setter
}
public class SessionManager{
//将Session放入redis
public void pushSession2Redis(Session session){
//这里就不用我说了吧
//不知道你自己用的redis客户端是什么
//调用客户端(比如Jedis)的API把session放到你自己的数据结构不就行了
}
//从redis获取指定session
public Session findById(String sessionId){
return null;
}
}
15 回答8.4k 阅读
8 回答6.2k 阅读
1 回答4k 阅读✓ 已解决
3 回答2.2k 阅读✓ 已解决
2 回答3.1k 阅读
2 回答3.8k 阅读
3 回答1.7k 阅读✓ 已解决
我的理解是题主要做netty分布式服务,
一般而言 netty 连接都是统一保存在map<key,Channel>中,key值为用户标识,主要问题在与多节点时,需要向用户发送消息如何知道用户在哪个节点上
解决方案有下面几种:
1.在redis 中存储一张路由表,记录用户所在服务节点,然后发送消息。
2.利用mq 统一向所有节点广播消息(消息内附带用户信息),节点收到消息后判断用户是否连接在本节点上,如果在则从map 中取出,并发送消息,否则丢弃.
3.另一种也是一种查找路由的方式,利用一致性Hash算法,查找用户所在服务节点.