这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战
Reactor线程模型
单线程模型
异步非阻塞i/o,所有的i/o操作都不会导致阻塞。理论上一个线程可以独立处理所有的i/o相关的操作。和node.js类似
多线程模型
和单线程相比多了一组线程组:
有一个nio线程负责处理客户端的连接;
增加了一组nio线程池来处理网络io操作
主要问题是一个线程处理客户端连接,可能存在安全和性能问题,例如并发百万客户端连接,或者服务端需要对客户端握手进行安全认证,但是认证本身非常损耗性能。
主从模式
为了解决上述的两种模式的缺点,这种模式是相对来说合理的,也是官网推荐的
采用的是一个线程池去处理客户端连接,监听客户端的连接包括安全认证,但是等到链路创建完成就创建一个线程去处理具体的业务逻辑
Bootstrapping
引导客户端和服务端构建netty应用
Boostrap
Bootstrap用来连接远程主机,有1个EventLoopGroup
ServerBootstrap
引导服务端完成netty配置
组件源码
ChannelHandler
channel处理器
// 在ChannelHandler添加到handlerContext中触发
void handlerAdded(ChannelHandlerContext ctx) throws Exception;
// 在ChannelHandler从context中移除时触发
void handlerRemoved(ChannelHandlerContext ctx) throws Exception;
// 异常捕获
@Deprecated
void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;
// 标注一个channel handler可以被多个channel安全地共享。
// 因为一个ChannelHandler可以从属于多个ChannelPipeline,所以它也可以绑定到多个ChannelHandlerContext实例。用于这种用法的ChannelHandler必须要使用@Sharable注解标注
@Inherited
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Sharable {
// no value
}
ChannelHandlerAdapter
实现ChannelHandler接口,新增如下两个方法
// 没有shared注解则抛出异常
protected void ensureNotSharable() {
if (isSharable()) {
throw new IllegalStateException("ChannelHandler " + getClass().getName() + " is not allowed to be shared");
}
}
/**
* 验证是否可被加入到ChannelPipline,建立缓存
*/
public boolean isSharable() {
Class<?> clazz = getClass();
Map<Class<?>, Boolean> cache = InternalThreadLocalMap.get().handlerSharableCache();
Boolean sharable = cache.get(clazz);
if (sharable == null) {
sharable = clazz.isAnnotationPresent(Sharable.class);
cache.put(clazz, sharable);
}
return sharable;
}