在许多框架中,都使用到了Netty作为网络通信的框架。比如Dobbo、RocketMQ等十分出名且使用广泛的框架中。
使用简便
在不使用Netty之前搭建一个服务器的代码如下所示:
java
代码解读
复制代码
// 服务器 public static void main(String[] args) { try (ServerSocketChannel channel = ServerSocketChannel.open()) { // 绑定端口 channel.bind(new InetSocketAddress(8080)); // 创建Selector 监听事件 Selector selector = Selector.open(); // 设置channel为非阻塞 channel.configureBlocking(false); // 将Channel注册到Selector中,并且监听连接事件 channel.register(selector, SelectionKey.OP_ACCEPT); while (true) { // 当有连接事件发生时,返回事件个数 int count = selector.select(); // 获取所有事件 Set<SelectionKey> keys = selector.selectedKeys(); // 遍历所有事件,逐一处理 Iterator<SelectionKey> iter = keys.iterator(); while (iter.hasNext()) { SelectionKey key = iter.next(); // 业务逻辑 iter.remove(); } } } catch (IOException e) { e.printStackTrace(); } } // 客户端 public static void main(String[] args) { try (SocketChannel channel = SocketChannel.open()) { channel.bind(new InetSocketAddress(8080)); // 编写业务代码 } catch (Exception e) { e.printStackTrace(); } }
需要编写大量的代码以及处理非常多的异常。
引入了Netty之后,代码就长这样了:
整理了一份好像面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题
需要全套面试笔记【点击此处即可】免费获取
java
代码解读
复制代码
// 服务端 public static void main(String[] args) { // 创建启动器 ServerBootstrap serverBootstrap = new ServerBootstrap(); // 设置线程组 serverBootstrap.group(getLoopGroup("zsk-server")); // 设置启动的Channel类型 serverBootstrap.channel(NioServerSocketChannel.class); // 添加业务逻辑Handler serverBootstrap.childHandler(new ServerInitializer()); // 一些连接的配置 serverBootstrap.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 30000); // 绑定端口 serverBootstrap.bind(8080); } // 客户端 public static void main(String[] args) { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(getLoopGroup("zsk-client")); bootstrap.channel(NioSocketChannel.class); // 编写业务handler bootstrap.handler(new ClientInitializer()); bootstrap.connect(new InetSocketAddress(8080)); }
代码清晰且简便,不需要自己处理服务器创建的逻辑,只需要关注业务逻辑代码的编写,简化开发。
一些性能的优化
优化SelectionKeySet
获取底层配置类
使用反射将内部原始的属性替换成自建的
将SelectorImpl
中的selectedKeys、publicSelectedKeys替换成Netty的SelectedSelectionKeySet
。
优秀的设计
- 对象池:由于
Netty
中有着许多被复用的对象,为了避免过度新增以及回收,将其池化。 - JNI:
Netty
在内部封装了一些本地native
方法,使用了C++的一些特性。 - ByteBuf:在Netty中,重新设计了一个用于字节处理的类:ByteBuf。该类对于JDK自带的
ByteBuffer
来说功能更加强大。 - 线程模型:所有读写操作都在一个线程内,省去了
volatile
等线程可见机制。不需要考虑并发的操作。
- 批量发送:将多次写入的数据一起发送出去,避免多次系统调用。(Java->JNI->c->用户空间->内核空间)
总结
Netty凭借其简洁的API设计、强大的功能和卓越的性能,成为了许多网络编程框架的首选,广泛应用于诸如Dubbo、RocketMQ等高性能分布式系统中。