本文已参与「新人创作礼」活动,一起开启掘金创作之路。
首先要知道netty 是多线程的。是基于Socket的。
1: 之前博主在netty 中用List 来存储channelId 并作唯一识别,但忽略了一点,List 是不安全的。 尤其是多线程环境下,会出现数据混乱的问题。
2: 出于安全考虑,又采取了Map 形式。如果只是用来存取channelId 肯定是没有问题。 但如果多个接口都去调取这个Map 呢? 似乎有所不妥。
3: 博主这边环境是一个外网的应用,去给内网推送数据。这边存取 channelId 也没有考虑去用什么缓存在存取,直接是static 共享。
解决方案:
连接时:
1:当有客户端连接时,就把客户端的channelId 记录下来。
2:建立连接,返回消息
断开时:
1:客户端主动断开服务器连接,关闭流。
2:断开连接
/**
* 当有客户端连接时,handlerAdded会执行,就把该客户端的通道记录下来,加入队列
* 连接第1步
* @param ctx
* @throws Exception
*/
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
channels.add(channel);
super.handlerAdded(ctx);
}
/**
* 建立连接时,返回消息
* 连接第2步
* @param ctx
* @throws Exception
*/
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
AttributeKey<String> host_channel_key = AttributeKey.valueOf("channel-host");
Attribute<String> attr = channel.attr(host_channel_key);
InetSocketAddress socketAddress = (InetSocketAddress) channel.remoteAddress();
String host = socketAddress.getHostString();
attr.set(host);
log.debug("通道号:[{}],客户端:[{}]: 在线",channel.toString(), channel.remoteAddress());
super.channelActive(ctx);
}
/**
* 客户端主动断开服务端的链接,关闭流
* */
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
log.debug("通道号:[{}],客户端:[{}]: 离线",channel.toString(), channel.remoteAddress());
super.channelInactive(ctx);
}
/**
* 断开连接 第2步
*
* @param ctx
* @throws Exception
*/
@Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
Channel channel = ctx.channel();
channels.remove(channel);
super.handlerRemoved(ctx);
ctx.channel().close();
}
最重要的一步。
public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
去看 DefaultChannelGroup 类中 add 方法
先不管,它是不是多线程的。 就看是否满足我们能现在的需要。 Channel channel = ctx.channel(); channels.add(channel); 到此我们已经把 channelId 放到了该放的地方。
那我们在回归开始:netty 它到底是不是多线程的。 博主能力有限,感兴趣的可以自己去看看。