Netty 中设计模式
单例模式源码举例
单例模式要点回顾:
- 一个类在任何情况下只有一个对象,并提供一个全局访问点。
- 可延迟创建。
- 避免线程安全问题。
案例分析:
@Sharable
public final class MqttEncoder extends MessageToMessageEncoder<MqttMessage> {
public static final MqttEncoder INSTANCE = new MqttEncoder();
private MqttEncoder() {
}
protected void encode(ChannelHandlerContext ctx, MqttMessage msg, List<Object> out) throws Exception {
out.add(doEncode(ctx.alloc(), msg));
}
...
}
策略模式源码举例
策略模式要点回顾:
- 封装一系列可相互替换的算法家族。
- 动态选择某一个策略。
案例分析:
public final class DefaultEventExecutorChooserFactory implements EventExecutorChooserFactory {
public static final DefaultEventExecutorChooserFactory INSTANCE = new DefaultEventExecutorChooserFactory();
private DefaultEventExecutorChooserFactory() {
}
public EventExecutorChooser newChooser(EventExecutor[] executors) {
return (EventExecutorChooser)(isPowerOfTwo(executors.length)?new DefaultEventExecutorChooserFactory.PowerOfTowEventExecutorChooser(executors):
new DefaultEventExecutorChooserFactory.GenericEventExecutorChooser(executors));
}
private static boolean isPowerOfTwo(int val) {
return (val & -val) == val;
}
...
}
装饰者模式源码举例
装饰者模式要点回顾:
- 装饰者和被装饰者实现同一个接口。
- 装饰者通常继承被装饰者,同宗同源。
- 动态修改、重载被装饰者的方法。
WrappedByteBuf :
class WrappedByteBuf extends ByteBuf {
protected final ByteBuf buf;
protected WrappedByteBuf(ByteBuf buf) {
if(buf == null) {
throw new NullPointerException("buf");
} else {
this.buf = buf;
}
}
...
}
UnreleasableByteBuf :
final class UnreleasableByteBuf extends WrappedByteBuf {
private SwappedByteBuf swappedBuf;
UnreleasableByteBuf(ByteBuf buf) {
super(buf);
}
...
public boolean release() {
return false;
}
public boolean release(int decrement) {
return false;
}
}
SimpleakAwareByteBuf:
final class SimpleLeakAwareByteBuf extends WrappedByteBuf {
private final ResourceLeak leak;
SimpleLeakAwareByteBuf(ByteBuf buf, ResourceLeak leak) {
super(buf);
this.leak = leak;
}
...
public boolean release() {
boolean deallocated = super.release();
if(deallocated) {
this.leak.close();
}
return deallocated;
}
public boolean release(int decrement) {
boolean deallocated = super.release(decrement);
if(deallocated) {
this.leak.close();
}
return deallocated;
}
}
观察者模式源码举例
观察者模式要点回顾:
- 两个角色:观察者和被观察者。
- 观察者订阅消息,被观察者发布消息。
- 订阅则能收到消息,取消订阅则收不到。
AbstractChannel: channel.writeAndFlush()方法:
public abstract class AbstractChannel extends DefaultAttributeMap implements Channel {
...
public ChannelFuture writeAndFlush(Object msg) {
return this.pipeline.writeAndFlush(msg);
}
public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
return this.pipeline.writeAndFlush(msg, promise);
}
...
}
迭代器模式源码举例
迭代器模式要点回顾:
- 实现迭代器接口
- 实现对容器中的各个对象逐个访问的方法。
public class CompositeByteBuf extends AbstractReferenceCountedByteBuf implements Iterable<ByteBuf> {
protected byte _getByte(int index) {
CompositeByteBuf.Component c = this.findComponent(index);
return c.buf.getByte(index - c.offset);
}
...
}
责任链模式源码举例
责任链:是指多个对象都有机会处理同一个请求,从而避免请求的发送者和接收者之间的耦合关系。然后,将这些对象连成一条链,并且沿着这条链往下传递请求,直到有一个对象可以处理它为止。在每个对象处理过程中,每个对象只处理它自己关心的那一部分,不相关的可以继续往下传递,直到链中的某个对象不想处理,可以将请求终止或丢弃。
责任链模式要点回顾:
- 需要有一个顶层责任处理接口(ChannelHandler)。
- 需要有动态创建链、添加和删除责任处理器的接口(ChannelPipeline)。
- 需要有上下文机制(ChannelHandlerContext)。
- 需要有责任终止机制(不调用 ctx.fireXXX()方法,则终止传播)。
AbstractChannelHandlerContext:
abstract class AbstractChannelHandlerContext extends DefaultAttributeMap implements ChannelHandlerContext, ResourceLeakHint {
private AbstractChannelHandlerContext findContextInbound() {
AbstractChannelHandlerContext ctx = this;
do {
ctx = ctx.next;
} while(!ctx.inbound);
return ctx;
}
}
工厂模式源码举例
工厂模式要点回顾:
1、将创建对象的逻辑封装起来。
ReflectiveChannelFactory:
public class ReflectiveChannelFactory<T extends Channel> implements ChannelFactory<T> {
private final Class<? extends T> clazz;
public ReflectiveChannelFactory(Class<? extends T> clazz) {
if(clazz == null) {
throw new NullPointerException("clazz");
} else {
this.clazz = clazz;
}
}
public T newChannel() {
try {
return (Channel)this.clazz.newInstance();
} catch (Throwable var2) {
throw new ChannelException("Unable to create Channel from class " + this.clazz, var2);
}
}
}
Netty 高性能并发调优
Netty 应用程序性能调优
// 90.0% == 1ms 1000 100 > 1ms
// 95.0% == 10ms 1000 50 > 10ms
// 99.0% == 100ms 1000 10 > 100ms
// 99.9% == 1000ms 1000 1 > 1000ms
单机百万连接调优解决思路
如何模拟百万连接
单机 1024 及以下的端口只能给 ROOT 保留使用,客户端(1025~65535)
Server 8000 Server 8000 ~ 8020
| 6W | 20 * 6
Client 1025 ~ 65535 Client 1025 ~ 65535
突破局部文件句柄限制
突破全局文件句柄限制
Netty 总结与面试答疑
-
Netty 定位:
- A、作为开源码框架的底层框架(TCP 通信)
- SpringBoot 内置的容器(Tomcat/Jerry)
- Zookeper 数据交互
- Dubbo 多协议 RPC 的支持
- B、直接做服务器(消息推送服务,游戏后台)
- A、作为开源码框架的底层框架(TCP 通信)
-
Netty 如何确定要使用哪些编码器和解码器
很简单,看 API 文档;Netty 自带的编解码器可以解决 99%的业务需求,1%自己编解码
-
Netty 中大文件上传的那个 handler 是怎么做到防止内存撑爆的
ByteBuf 分片,直接缓冲区,0 拷贝,提高内存的利用率 加内存 -
Tomcat NIO 方式的调优线程 ,本质上是对 netty 的调优吗
8.5 之后开始用 Netty?
-
责任链模式能否用在,一个操作出口参数为另一个操作的入口
执行顺序有关系,有先后
API 设计 callable(上一次调用的结果) ,msg(皮球) -
Netty 里面 Pooled 缓冲区和 Unpooled 缓冲区内存分配(在录播中讲解)
-
Linux 底层 IO 模型,主从,多路复用的思想(录制一个基于硬件层面 IO 模型,显得更加专业)
-
Selector 客户端与服务端之间是什么关系?
客户端:CONNECT READ WRITE
服务端:ACCEPT READ WRITE
评论区