Netty分布式NioEventLoop优化selector源码解析

网友投稿 1016 2022-10-17

Netty分布式NioEventLoop优化selector源码解析

Netty分布式NioEventLoop优化selector源码解析

目录优化selectorselector的创建过程代码剖析这里一步创建了这个优化后的数据结构最后返回优化后的selector

优化selector

selector的创建过程

在剖析selector轮询之前, 我们先讲解一下selector的创建过程

回顾之前的小节, 在创建NioEventLoop中初始化了唯一绑定的selector:

NioEventLoop(NioEventLoopGroup parent, Executor executor, SelectorProvider selectorProvider,

SelectStrategy strategy, RejectedExecutionHandler rejectedExecutionHandler) {

super(parent, executor, false, DEFAULT_MAX_PENDING_TASKS, rejectedExecutionHandler);

//代码省略

provider = selectorProvider;

selector = openSelector();

selectStrategy = strategy;

}

这里 selector = openSelector() 初始化了selector

我们跟到openSelector()中:

private Selector openSelector() {

final Selector selector;

try {

//调用jdk底层的api

selector = provider.openSelector();

} catch (IOException e) {

throw new ChannelException("failed to open a new selector", e);

}

//判断是否需要关闭优化(默认false, 也就是默认需要优化)

if (DISABLE_KEYSET_OPTIMIZATION) {

return selector;

}

//用这个数据结构替换原生的SelectionKeySet

final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();

Object maybeSelectorImplClass = AccessController.doPrivileged(new PrivilegedAction() {

@Override

public Object run() {

try {

//通过反射拿到sun.nio.ch.SelectorImpl这个类的class对象

return Class.forName("sun.nio.ch.SelectorImpl", false, PlatformDependent.getSystemClassLoader());

} catch (ClassNotFoundException e) {

return e;

} catch (SecurityException e) {

return e;

}

}

});

//判断拿到的是不是class对象并且是不是Selector的实现类

if (!(maybeSelectorImplClass instanceof Class) ||!((Class>) maybeSelectorImplClass).isAssignableFrom(selector.getClass())) {

if (maybeSelectorImplClass instanceof Exception) {

Exception e = (Exception) maybeSelectorImplClass;

logger.trace("failed to instrument a special java.util.Set into: {}", selector, e);

}

//如果不是他的实现, 就直接返回原生select

return selector;

}

//如果是它的实现, 就拿到其class对象

final Class> selectorImplClass = (Class>) maybeSelectorImplClass;

Object maybeException = AccessController.doPrivileged(new PrivilegedAction() {

@Override

public Object run() {

tryhttp:// {

//通过反射拿到selectedKeys和publicSelectedKeys两个属性, 默认这两个属性底层都是hashSet方式实现的

Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");

Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");

//设置成可修改的

selectedKeysField.setAccessible(true);

publicSelectedKeysField.setAccessible(true);

//将selector的这两个属性替换成Netty的selectedKeySet

selectedKeysField.set(selector, selectedKeySet);

publicSelectedKeysField.set(selector, selectedKeySet);

return null;

} catch (NoSuchFieldException e) {

return e;

} catch (IllegalAccessException e) {

return e;

} catch (RuntimeException e) {

if ("java.lang.reflect.InaccessibleObjectException".equals(e.getClass().getName())) {

return e;

} else {

throw e;

}

}

}

});

if (maybeException instanceof Exception) {

selectedKeys = null;

Exception e = (Exception) maybeException;

logger.trace("failed to instrument a special java.util.Set into: {}", selector, e);

} else {

//将优化后的keySet保存成NioEventLoop的成员变量

selectedKeys = selectedKeySet;

logger.trace("instrumented a special java.util.Set into: {}", selector);

}

return selector;

}

代码剖析

这里代码比较长, 我们一点一点的剖析:

首先 selector = provider.openSelector() 这里创建了jdk底层的selector

if (DISABLE_KEYSET_OPTIMIZATION) {

return selector;

}

这里判断了是否关闭优化功能, 默认是false, 也就是需要优化, 这里的意思就是netty需要对jdk原生的selector进行了优化, 我们知道selector在select()操作时候, 会通过selector.selectedKeys()操作返回一个Set, 这个是Set类型, netty对这个set进行了处理, 使用SelectedSelectionKeySet的数据结构进行替换, 当在select()操作时将key存入一个SelectedSelectionKeySet的数据结构中

final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();

这里一步创建了这个优化后的数据结构

简单跟一下SelectedSelectctionKeySet这个类的构造方法:

SelectedSelectionKeySet() {

keysA = new SelectionKey[1024];

keysB = keysA.clone();

}

初始化了两个属性keysA和keysB, 说明这类其实底层是通过数组实现的, 通过操作数组下标会有更高的效率

这个类的的flip()方法, 则返SelectionKey[]数组

SelectionKey[] flip() {

if (isA) {

isA = false;

keysA[keysASize] = null;

keysBSize = 0;

return keysA;

} else {

isA = true;

keysB[keysBSize] = null;

keysASize = 0;

return keysB;

}

}

再看下其他方法:

@Override

public boolejsLYiYBcan remove(Object o) {

return false;

}

@Override

public boolean contains(Object o) {

return false;

}

@Override

public Iterator iterator() {

throw new UnsupportedOperationException();

}

我们看到remove()方法, contains()方法都返回了false, 说明其不支持删除方法和包含方法, iterator()方法则直接抛出异常, 说明其不支持迭代器操作

回到openSelector()中:

再往下看, 这里通过 Class.forName("sun.nio.ch.SelectorImpl", false, PlatformDependent.getSystemClassLoader()) 创建了一个SelectorImpl的class对象

if(!(maybeSelectorImplClass instanceof Class) ||!((Class>) maybeSelectorImplClass).isAssignableFrom(selector.getClass()))

这里判断拿到的对象是否为class对象并且是否为Selector的实现类, 如果不是, 则直接返回jdk的selector

如果是, 就继续转化成class对象

然后就做了真正的替换操作:

//通过反射拿到selectedKeys和publicSelectedKeys两个属性, 默认这两个属性底层都是hashSet方式实现的

Field selectedKeysField = selectorImplClass.getDeclaredField("selectedKeys");

Field publicSelectedKeysField = selectorImplClass.getDeclaredField("publicSelectedKeys");

//设http://置成可修改的

selectedKeysField.setAccessible(true);

publicSelectedKeysField.setAccessible(true);

//将selector的这两个属性替换成Netty的selectedKeySet

selectedKeysField.set(selector, selectedKeySet);

publicSelectedKeysField.set(selector, selectedKeySet);

通过注释我们不难看出, 这里将新创建selectedKeySet替换了selector对象中的selectedKeysField, 和selectedKeysField两个属性

最后通过 selectedKeys = selectedKeySet 将优化的数据结构selectedKeySet保存在NioEventLoop的成员变量中

最后返回优化后的selector

这样, selector在select()操作的过程中, 如果有就绪事件则会将返回的key存放在selectedKeySet所对应的数组中

以上就是Netty分布式NioEventLoop优化selector源码解析的详细内容,更多关于Netty分布式NioEventLoop优化selector的资料请关注我们其它相关文章!

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SpringMVC 异常信息ASM ClassReader failed to parse class file的问题解决
下一篇:linux 安装swoole
相关文章

 发表评论

暂时没有评论,来抢沙发吧~