好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

优化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源码解析的详细内容...

  阅读:20次