Netty系列之为什么Netty是网络编程的首选

在许多框架中,都使用到了Netty作为网络通信的框架。比如DobboRocketMQ等十分出名且使用广泛的框架中。

使用简便

在不使用Netty之前搭建一个服务器的代码如下所示:

// 服务器
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之后,代码就长这样了:

// 服务端
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

获取底层配置类

image.png

使用反射将内部原始的属性替换成自建的

image.png
SelectorImpl中的selectedKeyspublicSelectedKeys替换成Netty的SelectedSelectionKeySet

优秀的设计

  • 对象池:由于Netty中有着许多被复用的对象,为了避免过度新增以及回收,将其池化。
  • JNI:Netty在内部封装了一些本地native方法,使用了C++的一些特性。
  • ByteBuf:在Netty中,重新设计了一个用于字节处理的类:ByteBuf。该类对于JDK自带的ByteBuffer来说功能更加强大。
  • 线程模型:所有读写操作都在一个线程内,省去了volatile等线程可见机制。不需要考虑并发的操作。

  • 批量发送:将多次写入的数据一起发送出去,避免多次系统调用。(Java->JNI->c->用户空间->内核空间)

总结

Netty凭借其简洁的API设计、强大的功能和卓越的性能,成为了许多网络编程框架的首选,广泛应用于诸如Dubbo、RocketMQ等高性能分布式系统中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值