优化selector
selector的创建过程
在剖析selector轮询之前, 我们先讲解一下selector的创建过程
回顾之前的小节, 在 创建NioEventLoop 中初始化了唯一绑定的selector:
1 2 3 4 5 6 7 8 |
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()中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
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<Object>() { @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<Object>() { @Override public Object run() { try { //通过反射拿到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
1 2 3 |
if (DISABLE_KEYSET_OPTIMIZATION) { return selector; } |
这里判断了是否关闭优化功能, 默认是false, 也就是需要优化, 这里的意思就是netty需要对jdk原生的selector进行了优化, 我们知道selector在select()操作时候, 会通过selector.selectedKeys()操作返回一个Set<SelectionKey>, 这个是Set类型, netty对这个set进行了处理, 使用SelectedSelectionKeySet的数据结构进行替换, 当在select()操作时将key存入一个SelectedSelectionKeySet的数据结构中
1 |
final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet(); |
这里一步创建了这个优化后的数据结构
简单跟一下SelectedSelectctionKeySet这个类的构造方法:
1 2 3 4 |
SelectedSelectionKeySet() { keysA = new SelectionKey[ 1024 ]; keysB = keysA.clone(); } |
初始化了两个属性keysA和keysB, 说明这类其实底层是通过数组实现的, 通过操作数组下标会有更高的效率
这个类的的flip()方法, 则返SelectionKey[]数组
1 2 3 4 5 6 7 8 9 10 11 12 13 |
SelectionKey[] flip() { if (isA) { isA = false ; keysA[keysASize] = null ; keysBSize = 0 ; return keysA; } else { isA = true ; keysB[keysBSize] = null ; keysASize = 0 ; return keysB; } } |
再看下其他方法:
1 2 3 4 5 6 7 8 9 10 11 12 |
@Override public boolean remove(Object o) { return false ; } @Override public boolean contains(Object o) { return false ; } @Override public Iterator<SelectionKey> 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对象
然后就做了真正的替换操作:
1 2 3 4 5 6 7 8 9 |
//通过反射拿到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); |
通过注释我们不难看出, 这里将新创建selectedKeySet替换了selector对象中的selectedKeysField, 和selectedKeysField两个属性
最后通过 selectedKeys = selectedKeySet 将优化的数据结构selectedKeySet保存在NioEventLoop的成员变量中
最后返回优化后的selector
这样, selector在select()操作的过程中, 如果有就绪事件则会将返回的key存放在selectedKeySet所对应的数组中
以上就是Netty分布式NioEventLoop优化selector源码解析的详细内容,更多关于Netty分布式NioEventLoop优化selector的资料请关注其它相关文章!
原文链接:https://www.cnblogs.com/xiangnan6122/p/10203116.html
查看更多关于Netty分布式NioEventLoop优化selector源码解析的详细内容...