分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 技术分享

Netty源码分析第2章(NioEventLoop)---->第5节: 优化selector

发布时间:2023-09-06 02:28责任编辑:赖小花关键词:暂无标签

 

第二章: NioEventLoop

 

第五节: 优化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<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

if (DISABLE_KEYSET_OPTIMIZATION) { ???return selector;}

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

final SelectedSelectionKeySet selectedKeySet = new SelectedSelectionKeySet();

这里一步创建了这个优化后的数据结构, 简单跟一下这个类的构造方法:

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; ???}}

再看下其他方法:

@Overridepublic boolean remove(Object o) { ???return false;}@Overridepublic boolean contains(Object o) { ???return false;}@Overridepublic Iterator<SelectionKey> iterator() { ???throw new UnsupportedOperationException();}

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

再往下看, 这里通过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");//设置成可修改的selectedKeysField.setAccessible(true);publicSelectedKeysField.setAccessible(true);//将selector的这两个属性替换成Netty的selectedKeySetselectedKeysField.set(selector, selectedKeySet);publicSelectedKeysField.set(selector, selectedKeySet);

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

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

最后返回优化后的selector

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

 

 

Netty源码分析第2章(NioEventLoop)---->第5节: 优化selector

原文地址:https://www.cnblogs.com/xiangnan6122/p/10203116.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved