目录导航
前言
本节我们就需要基于 Netty 开发(已熟练掌握 Netty 操作 API 的)的人群,谈谈Netty的性能调优。
Netty共计分为六节,分别是:
- 01 Java IO 演进之路
- 02 Netty与NIO之前世今生
- 03 Netty初体验之重构RPC框架
- 04 Netty核心之Netty高性能之道
- 05 Netty核心之大动脉 Pipeline与EventLoop
- 06 Netty实战之性能调优与设计模式
本节重点:
➢ 了解设计模式在 Netty 中的应用
➢ 了解实际应用中 Netty 的性能调优解决方案
设计模式在 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;
}
}
观察者模式源码举例
观察者模式要点回顾:
- 两个角色:观察者和被观察者。
- 观察者订阅消息,被观察者发布消息。
- 订阅则能收到消息,取消订阅则收不到。
channel.writeAndFlush()方法:
AbstractChannel:
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;
}
}
工厂模式源码举例
工厂模式要点回顾:
- 将创建对象的逻辑封装起来。
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
具体代码详见本节末github地址
单机百万连接调优解决思路
如何模拟百万连接?
单机 1024 及以下的端口只能给 ROOT 保留使用,客户端(1025~65535)
关于如何突破局部文件句柄限制,如何突破全局文件句柄限制,请自行查阅,这里不再赘述
后记
Netty相关的全部演示代码的下载地址:
https://github.com/harrypottry/nettydemo
更多架构知识,欢迎关注本套Java系列文章:Java架构师成长之路