【Netty之初体验】

2020-03-19 09:51:24 浏览数 (1)

什么是Netty? Netty 是一个利用 Java 的高级网络的能力,隐藏其背后的复杂性而提供一个易于使用的 API 的客户端/服务器框架。 Netty 是一个广泛使用的 Java 网络编程框架。 Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server. 'Quick and easy' doesn't mean that a resulting application will suffer from a maintainability or a performance issue. Netty has been designed carefully with the experiences earned from the implementation of a lot of protocols such as FTP, SMTP, HTTP, and various binary and text-based legacy protocols. As a result, Netty has succeeded to find a way to achieve ease of development, performance, stability, and flexibility without a compromise. Netty是一个NIO客户机-服务器框架,它支持快速而容易地开发网络应用程序,如协议服务器和客户机。它大大简化和简化了网络编程,如TCP和UDP套接字服务器。

“快速简单”并不意味着生成的应用程序将遭受可维护性或性能问题的困扰。Netty经过了精心的设计,其经验来自于FTP、SMTP、HTTP以及各种基于二进制和文本的遗留协议的实现。因此,Netty成功地找到了一种不妥协地实现易开发性、性能、稳定性和灵活性的方法。

设计 各种传输类型的统一API.阻塞和非阻塞套接字 基于灵活和可扩展的事件模型,允许清晰地分离关注点 高度可定制的线程模型-单线程、一个或多个线程池,如SEDA 真正的无连接数据报套接字支持(从3.1开始) 易用性 有据可查的Javadoc、用户指南和示例 没有其他依赖项,JDK 5(Netty 3.x)或6(Netty 4.x)就足够了 注意:某些组件(如HTTP/2)可能有更高的要求。有关详细信息,请参阅要求页。 性能 更好的吞吐量,更低的延迟 减少资源消耗 最小化不必要的内存复制(可以理解为零拷贝) 安全 完整的SSL/TLS和StartTLS支持

Netty高并发

当一个连接建立之后,他有两个步骤要做,第一步是接收完客户端发过来的全部数据,第二步是服务端处理完请求业务之后返回response给客户端。NIO和BIO的区别主要是在第一步。

在BIO中,等待客户端发数据这个过程是阻塞的,这样就造成了一个线程只能处理一个请求的情况,而机器能支持的最大线程数是有限的,这就是为什么BIO不能支持高并发的原因。

而NIO中,当一个Socket建立好之后,Thread并不会阻塞去接受这个Socket,而是将这个请求交给Selector,Selector会不断的去遍历所有的Socket,一旦有一个Socket建立完成,他会通知Thread,然后Thread处理完数据再返回给客户端——这个过程是不阻塞的,这样就能让一个Thread处理更多的请求了。

Netty为什么传输快 我们知道,Java的内存有堆内存、栈内存和字符串常量池等等,其中堆内存是占用内存空间最大的一块,也是Java对象存放的地方,一般我们的数据如果需要从IO读取到堆内存,中间需要经过Socket缓冲区,也就是说一个数据会被拷贝两次才能到达他的的终点,如果数据量大,就会造成不必要的资源浪费。 Netty针对这种情况,使用了NIO中的另一大特性——零拷贝,当他需要接收数据的时候,他会在堆内存之外开辟一块内存,数据就直接从IO读到了那块内存中去,在netty里面通过ByteBuf可以直接对这些数据进行直接操作,从而加快了传输速度。

--------

参考: https://www.jianshu.com/p/b9f3f6a16911 (认识Netty)

附代码参考:

代码语言:javascript复制
/**
 * @Author: Liu Yue
 * @Descripition:
 * @Date; Create in 2020/3/15 10:19
 **/
public class LYntServer {

    private int port;

    public LYntServer(int port) {
        this.port = port;
    }

    public void start() throws InterruptedException {
        //ServerSocket
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        ServerBootstrap serverBootstrap = new ServerBootstrap();

        serverBootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        //在netty中,把所有业务逻辑处理全部归总到了一个队列中;
                        //此队列中包含了各种各样的处理逻辑
                        ChannelPipeline pipeline = ch.pipeline();

                        //对于自定义协议的内容进行编码解码
                        pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
                        //自定义编码器
                        pipeline.addLast(new LengthFieldPrepender(4));
                        //实参处理
                        pipeline.addLast("encoder", new ObjectEncoder());
                        pipeline.addLast("decoder", new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)));

                        pipeline.addLast(new LYRegistryHandler());
                    }
                }).option(ChannelOption.SO_BACKLOG, 128)
                .childOption(ChannelOption.SO_KEEPALIVE, true);
        //正式启动服务,相当于用一个死循环开始提供服务
        ChannelFuture sync = serverBootstrap.bind(this.port).sync();
        System.out.println("RPC服务启动监听:" port );
        sync.channel().closeFuture().sync();
    }

    public static void main(String[] args) throws InterruptedException {
        new LYntServer(8080).start();
    }
}

启动成功:

客户端调用顺序

每日提高一点点

0 人点赞