import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.IntStream;
/**
* websocket 上下文
*/
public class WebSocketContext {
private static final int CHANNEL_MAP_NUM = 256;
private static final String USER_ID = "userId";
public static final AttributeKey<String> ATTR_KEY_USER_ID = AttributeKey.valueOf(USER_ID);
/**
* 将全局map拆分成多个(数量:CHANNEL_MAP_NUM),以减小同步锁压力,提高性能
*/
private static final Map<Integer,Map<String,Channel>> ALL_CHANNEL_MAP = new ConcurrentHashMap<>(CHANNEL_MAP_NUM);
static {
//初始化ALL_CHANNEL_MAP
IntStream.range(0,CHANNEL_MAP_NUM-1).forEach(x->ALL_CHANNEL_MAP.put(x,new ConcurrentHashMap<>()));
}
public static void addChannel(String userId, Channel channel){
Attribute<String> channelAttrUserId = channel.attr(ATTR_KEY_USER_ID);
channelAttrUserId.set(userId);
getChannelMap(userId).put(userId,channel);
}
public static Channel getChannel(String userId){
return getChannelMap(userId).get(userId);
}
public static void removeChannel(String userId){
getChannelMap(userId).remove(userId);
}
/**
* 根据用户ID找到相应的Channel Map
* @param userId userId
* @return channel map
*/
private static Map<String,Channel> getChannelMap(String userId){
return ALL_CHANNEL_MAP.get(getChannelMapIndex(userId));
}
/**
* 根据用户ID获取index = hash(userId) % CHANNEL_MAP_NUM
* @param userId 用户ID
* @return channel map index
*/
private static int getChannelMapIndex(String userId){
return userId.hashCode() % CHANNEL_MAP_NUM;
}
//todo 如性能差sendMsg及各种重载可做优化
public static void sendMsg(String usrId,byte[] data){
sendMsg(getChannel(usrId),data);
}
public static void sendMsg(Channel channel,byte[] data){
if (channel == null) {
return;
}
ByteBuf buffer = channel.alloc().buffer(data.length);
channel.writeAndFlush(new BinaryWebSocketFrame(buffer.writeBytes(data)));
}
public static void sendMsg(Collection<String> users, byte[] data){
for(String userId:users){
sendMsg(userId,data);
}
}
}
将全局map拆分成多个(数量:CHANNEL_MAP_NUM),以减小同步锁压力,提高性能
最新推荐文章于 2022-03-02 18:34:32 发布