Serie Netty: uso del protocolo de transporte nativo en netty

Introducción

Para IO, además del tradicional bloque IO, el más utilizado es NIO, normalmente el más utilizado en programas de red es NIO, como NioEventLoopGroup, NioServerSocketChannel, etc.

También sabemos que existen métodos de IO más rápidos que NIO en IO, como kqueue y epoll, pero estos dos métodos requieren el soporte de métodos nativos, lo que significa que los servicios deben proporcionarse a nivel del sistema operativo.

Si estamos en un servidor que admite Kqueue o epoll, ¿Netty puede brindar soporte para estos excelentes IO?

La respuesta es sí. Pero primero kqueue y epoll necesitan compatibilidad con JNI, lo que significa que los programas JAVA deben llamar a métodos nativos locales.

dependencias del protocolo de transporte nativo

Para usar los métodos de transmisión nativos de kequeue y epoll, necesitamos agregar dependencias adicionales del proyecto. Si se trata de un entorno Linux, puede agregar el siguiente entorno de dependencia maven:

  <dependencies>
    <dependency>
      <groupId>io.netty</groupId>
      <artifactId>netty-transport-native-epoll</artifactId>
      <version>${project.version}</version>
      <classifier>linux-x86_64</classifier>
    </dependency>
    ...
  </dependencies>
复制代码

La versión debe coincidir con el número de versión de netty que está utilizando; de lo contrario, puede ocurrir una llamada anormal.

El clasificador representa la arquitectura del sistema y su valor puede ser linux-x86_64 o linux-aarch_64.

Si está utilizando un sistema mac, puede importarlo así:

  <dependencies>
    <dependency>
      <groupId>io.netty</groupId>
      <artifactId>netty-transport-native-kqueue</artifactId>
      <version>${project.version}</version>
      <classifier>osx-x86_64</classifier>
    </dependency>
    ...
  </dependencies>
复制代码

Además de un paquete individual separado, netty también tiene un paquete netty-all todo en uno. Si usa este paquete todo en uno, no necesita agregar dependencias nativas adicionales.

Si la arquitectura del sistema proporcionada por netty no es la que está utilizando, entonces necesita compilarla manualmente. Los siguientes son los paquetes de los que depende la compilación. Si es en un sistema RHEL/CentOS/Fedora, use:

sudo yum install autoconf automake libtool make tar \
                 glibc-devel \
                 libgcc.i686 glibc-devel.i686
复制代码

Si está en un sistema Debian/Ubuntu, use:

sudo apt-get install autoconf automake libtool make tar \
                     gcc
复制代码

Si está en un sistema MacOS/BSD, use:

brew install autoconf automake libtool
复制代码

El uso del protocolo de transporte local netty

Después de instalar las dependencias, podemos usar estos protocolos de transporte nativos en netty.

El uso del protocolo de transmisión nativo es básicamente el mismo que el uso de NIO, solo necesitamos hacer las siguientes sustituciones.

Si está en el sistema liunx, haga las siguientes sustituciones:

    NioEventLoopGroup → EpollEventLoopGroup
    NioEventLoop → EpollEventLoop
    NioServerSocketChannel → EpollServerSocketChannel
    NioSocketChannel → EpollSocketChannel
复制代码

Si está en un sistema mac, haga las siguientes sustituciones:

    NioEventLoopGroup → KQueueEventLoopGroup
    NioEventLoop → KQueueEventLoop
    NioServerSocketChannel → KQueueServerSocketChannel
    NioSocketChannel → KQueueSocketChannel
复制代码

这里还是使用我们熟悉的聊天服务为例,首先看下基于Kqueue的netty服务器端应该怎么写:

EventLoopGroup bossGroup = new KQueueEventLoopGroup(1);
        EventLoopGroup workerGroup = new KQueueEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(KQueueServerSocketChannel.class)
             .handler(new LoggingHandler(LogLevel.INFO))
             .childHandler(new NativeChatServerInitializer());

            Channel channel = b.bind(PORT).sync().channel();
            log.info("server channel:{}", channel);
            channel.closeFuture().sync();
复制代码

和NIO一样,在服务器端我们需要使用KQueueEventLoopGroup创建两个EventLoopGroup,一个是bossGroup, 一个是workerGroup。

然后将这两个group传入到ServerBootstrap中,并且添加KQueueServerSocketChannel作为channel。

其他的内容和NIO server的内容是一样的。

接下来我们看下基于Kqueue的netty客户端改如何跟server端建立连接:

EventLoopGroup group = new KQueueEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group)
             .channel(KQueueSocketChannel.class)
             .handler(new NativeChatClientInitializer());

            // 建立连接
            Channel ch = b.connect(HOST, PORT).sync().channel();
            log.info("client channel: {}", ch);
复制代码

这里使用的是KQueueEventLoopGroup,并将KQueueEventLoopGroup放到Bootstrap中,并且为Bootstrap提供了和server端一致的KQueueSocketChannel。

然后就是客户端向channel中写消息,这里我们直接从命令行输入:

// 从命令行输入
            ChannelFuture lastWriteFuture = null;
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            for (;;) {
                String line = in.readLine();
                if (line == null) {
                    break;
                }
                // 将从命令行输入的一行字符写到channel中
                lastWriteFuture = ch.writeAndFlush(line + "\r\n");
                // 如果输入'再见',则等待server端关闭channel
                if ("再见".equalsIgnoreCase(line)) {
                    ch.closeFuture().sync();
                    break;
                }
            }
复制代码

上面代码的意思是将命令行收到的消息写入到channel中,如果输入的是’再见’,则关闭channel。

为了能够处理字符串,这里用到了三个编码解码器:

        // 添加行分割器
        pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
        // 添加String Decoder和String Encoder,用来进行字符串的转换
        pipeline.addLast(new StringEncoder());
        pipeline.addLast(new StringDecoder());
复制代码

分别是行分割器,字符编码器和字符解码器。

运行一下看,程序运行没问题,客户端和服务器端可以进行通讯。

总结

这里我们只以Kqueue为例介绍了netty中native传输协议的使用,具体的代码,大家可以参考:

learn-netty4

更多内容请参考 www.flydean.com/52-netty-na…

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

Supongo que te gusta

Origin juejin.im/post/7101610658185084936
Recomendado
Clasificación