一、DefaultEventExecutorChooseFactory
- DefaultEventExecutorChooseFactory选择器工厂
- DefaultEventExecutorChooseFactory这个事件执行选择器工厂是在Netty的并发包里面,
io.netty.util.concurrent
而且并注解UnstableApi
标志
UnstableApi注解类这样指出的,(
基于internal的工具类切记少用点
)
1、使用指南:位于.internal.包中的内容是否不需要
2、只有公共可访问的类/接口必须被注释,
3、如果该注释不存在,则认为API是稳定的,因此在非主要版本中不能破坏向后兼容性!
二、算法
- round-robin 思想编程在负载均衡场景使用(轮询算法)
-
Netty使用了二的指数算法进行事件选择(isPowerOfTwo),从哪里可以看出来它是用了二的指数算法呢,从 EventExecutorChooserFactory接口 跟踪进去的EventExecutorChooser,然后通过IDEA工具可以鼠标点击绿色图标可以调出查看。
EventExecutorChooserFactory#EventExecutorChooser - isPowerOfTwo关键代码
//事件执行选择器
public EventExecutorChooser newChooser(EventExecutor[] executors) {
//isPowerOfTwo二的指数算法进行事件选择
if (isPowerOfTwo(executors.length)) {
return new PowerOfTwoEventExecutorChooser(executors);
} else {
return new GenericEventExecutorChooser(executors);
}
}
//处理isPowerOfTwo
private static boolean isPowerOfTwo(int val) {
return (val & -val) == val;
}
//PowerOfTwo事件执行选择器
private static final class PowerOfTwoEventExecutorChooser implements EventExecutorChooser {
//原子性的Integer类型类
private final AtomicInteger idx = new AtomicInteger();
private final EventExecutor[] executors; //事件执行器
//PowerOfTwo事件执行选择器构造方法
PowerOfTwoEventExecutorChooser(EventExecutor[] executors) {
this.executors = executors;
}
@Override//下一个事件执行器
public EventExecutor next() {
return executors[idx.getAndIncrement() & executors.length - 1];
}
}
- DefaultEventExecutorChooserFactory (
round-robin
)
/**
* Default implementation which uses simple round-robin to choose next {@link EventExecutor}.
* 默认使用round-robin算法选择下一个实例的EventExecutor实现
* round-robin:主要用在负载均衡方向,比如有5台机器,第一次分请求到了第一台机器,第二次到了第二台机器,第三次请求到了第三台请求,以此类推一直到第五台机器,然后第六次又到了第一台机器,这样一个轮流的调用,处理负载,这里的Executor数组也是使用这种方式,保证数组里边的EventExecutor被均衡调用。
*/
public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory {
public EventExecutorChooser newChooser(EventExecutor[] executors) {
if (isPowerOfTwo(executors.length)) {
return new PowerOfTwoEventExecutorChooser(executors);
} else {
return new GenericEventExecutorChooser(executors);
}
}
三、加权
- 加权让性能好的机器在集群中选择的机率较为大,配置低的机器选择较低或概率小
四、SingleThreadEventLoop
- SingleThreadEventLoop针对EventLoop的抽象的父类会将所有被提交的任务当个线程去执行,它是一个单线程的事件循环对象
@Override //管道注册
public ChannelFuture register(Channel channel) {
//返回一个注册(register)的复合管道
return register(new DefaultChannelPromise(channel, this));
}
@Override//复合管道注册
public ChannelFuture register(final ChannelPromise promise) {
ObjectUtil.checkNotNull(promise, "promise");
promise.channel().unsafe().register(this, promise);
return promise;
}
-
promise.channel().unsafe().register(this, promise);的Channel接口的Unsafe的接口的方法,可以看出AbstractChannel类的内部类的AbstractUnsafe的register注册方法,而且AbstractUnsafe是一个抽象类.
AbstractUnsafe - AbstractChanne类重要的方法,如:
doBind
,doDisconnect
,doDeregister
、connect
、 - AbstractChanne的AbstractUnsafe内部类l许多比较重要的方法,如:
register0
、register
、deregister
、safeSetSuccess
、safeSetFailure
、recvBufAllocHandle
、invokeLater
更多请看截图
五、 Unsafe
Unsafe 提供内部类使用,提供不安全的操作,在Channel接口定义
六、MultithreadEventLoopGroup类
- MultithreadEventLoopGroup有注册入口处理,
register
代码如下:
@Override
public EventLoop next() {
return (EventLoop) super.next();
}
@Override
public ChannelFuture register(Channel channel) {
//此时这个next方法是上面的 public EventLoop next()
return next().register(channel);
}
6.1 register的实现类.
-
return next().register(channel);的实现类.
方法点击进去几个类进行实现register
f方法EmbeddedEventLoop、MultithreadEventLoopGroup、SingleThreadEventLoop、ThreadPerChannelEventLoopGroup、如图所示:
image.png 、
6.2 ThreadPerChannelEventLoopGroup代码分析.
- 咱们以典型的ThreadPerChannelEventLoopGroup进行跟踪一下代码
@Override
public ChannelFuture register(Channel channel) {
//判断管道对象是否为空,是空就返回空指针操作
if (channel == null) {
throw new NullPointerException("channel");
}
try {
EventLoop l = nextChild(); //事件循环
//返回一个事件循环注册的默认复合管道处理
return l.register(new DefaultChannelPromise(channel, l));
} catch (Throwable t) {
return new FailedChannelFuture(channel, GlobalEventExecutor.INSTANCE, t);
}
}
网友评论