Preparação da entrevista - resumo JAVA NIO e Netty

Este artigo é um resumo combinado com JavaGuide

Conhecimento básico de IO

Princípios básicos de leitura e escrita IO

readChamadas de writesistema e chamadas de sistema são apenas operações no buffer do kernel e no buffer do processo.

A chamada do sistema de leitura copia os dados do buffer do kernel para o buffer do processo

A chamada do sistema de gravação copia os dados do buffer do processo para o buffer do kernel.

至于具体的内核缓冲区到磁盘的过程则由操作系统内核进行.
Pode-se ver que as operações de IO de programas do usuário, como Socket e file IO, são todas de desenvolvimento de aplicativo de nível superior e seu processamento de entrada e saída são consistentes no processo de programação.

A função dos buffers

Reduza a troca frequente de dados com dispositivos físicos. Ocorrerá uma interrupção durante o processo de gravação de dados no disco. Quando o sistema é interrompido, o sistema precisa manter as informações de processo correspondentes e deve ser restaurado após a interrupção. O buffer reduz a sobrecarga dessa interrupção para o sistema.

Quatro modelos principais de IO

  • Bloqueio de E / S: refere-se ao estado do programa de espaço do usuário. Após a operação de IO do kernel ser completamente concluída, ele retorna ao espaço do usuário para realizar as operações do usuário. O soquete criado por padrão em Java está bloqueando IO
  • IO síncrono e IO assíncrono: IO
    síncrono significa que o encadeamento do programa de espaço do usuário é a parte que inicia IO, e o espaço do kernel é a parte que aceita passivamente.
    IO assíncrono refere-se à parte que inicia o IO no espaço do kernel e o programa do espaço do usuário é a parte aceitante.

同步阻塞IO(Blocking IO): O programa do usuário precisa aguardar a conclusão da operação de E / S do kernel antes de continuar.

同步非阻塞IO(Non-bolcking IO):O programa do usuário não precisa esperar a conclusão da operação IO do kernel para realizar a próxima operação. Durante esse processo, o kernel retornará um valor de status para o espaço do usuário.
Não NIO em JAVA (Novo IO)

IO多路复用又称为异步阻塞IO,就是Reactor反应器模式,Java中的Selector选择器和Linux中的epoll都是这种模型。

异步IO(Asynchronous IO): As threads do processo do usuário registram várias funções de retorno de chamada de evento de IO no espaço do kernel, que são ativamente chamadas pelo kernel.

Como oferecer suporte a milhões de conexões simultâneas por meio de uma configuração razoável

Ao desenvolver um sistema de alta simultaneidade, é necessário eliminar as restrições de manipulação de arquivos do Linux. O padrão do Linux é 1024. Ou seja, um processo pode aceitar 1024 conexões de soquete.

Identificador de arquivo, também chamado de descritor de arquivo.文件句柄是内核为了高效管理已经被打开的文件所常创建的索引。

Linux通过ulimite -n 文件句柄数量 来修改文件句柄数. Mas esse método só é eficaz quando o usuário efetua login.
Se você deseja modificá-lo permanentemente, você precisa modificar o /etc/rc.localarquivo de inicialização e adicionar: ulimite -SHnquantidade.
Você também pode etc/secuity/limites.conf’
adicionar diretamente o seguinte conteúdo por meio de modificação :

soft nofile 1000000 //(最大值为100万)
hard nofile 1000000
//soft nofile表示软性极限,
//hard nofile表示硬性极限,

Java NIO

Java NIO (New IO) foi introduzido no Java 4 para resolver o problema de bloqueio síncrono orientado a stream, portanto, muitas pessoas também o chamam de Non-Block IO.
Java NIO também pertence ao modelo de multiplexação IO.

NIO consiste em três componentes principais: Seletor de seletor de buffer de
canal

A diferença entre NIO e OIO

OIO foi usado antes do Java4, IO de bloqueio síncrono orientado a fluxo, fluxo de bytes ou fluxo de caracteres, ler dados do fluxo de bytes (fluxo de caracteres). Ler um ou mais de cada vez não pode alterar a posição do ponteiro à vontade. OIO não tem o conceito de seletor

NIO foi introduzido por Java4 para resolver IO de bloqueio síncrono e IO de não bloqueio orientado por buffer. Cada leitura é do canal para o buffer, e a operação de gravação é do buffer para o canal.
Você pode ler dados em qualquer lugar do buffer.

  • Como o NIO consegue não bloquear?
    Através da tecnologia de multiplexação de canais e canais
  • NIO tem o conceito de seletor, e a implementação de NIO é baseada na chamada do seletor do sistema.

Como usar o Buffer

  • Use o método allocate () para criar um objeto buffer
  • Use put para gravar dados no buffer pool
  • Use filp () para mudar o modo de gravação para o modo de leitura
  • Use get () para ler os dados do buffer
  • Após a leitura, você pode usar o método Buffer.clear () ou Buffe.compat () para mudar o buffer para o modo de gravação.

Tipo de canal

  • FileChannel文件通道, Usado para ler e gravar dados de arquivos
  • SocketChannel套接字通道, Usado para conexão TCP socket socket e leitura e gravação de dados. Normalmente usado ServerSoketChannel descentralizado para conexão.
  • ServerSocketChannel服务器套接字通道, Permite ouvir as solicitações de conexão TCP e criar um SockeTChannel para cada solicitação de conexão.
  • DatagramChannl数据报通道: Usado para leitura e gravação de dados UDP.

Ao usar o SocketChannel, o padrão é o bloqueio síncrono, portanto, ele precisa ser chamado configureBlocking(false)para configurar e se tornar o IO sem bloqueio assíncrono.

NIO Selector

A função do seletor é completar a multiplexação IO. Um canal representa uma conexão, e a função de monitorar vários canais de conexão pode ser realizada por meio do seletor. Permite que um thread conclua o monitoramento de vários canais.

  1. Tipo de evento de IO do seletor
  • Leia OP_READ
  • OP_WRITE gravável
  • A conexão de OP_CONNECT concluiu o handshake da extremidade oposta e está no 连接就绪estado.
  • Ao receber OP_ACCEPT, está em 接收就绪estado de transição quando uma nova conexão é detectada .
  1. FileChannelNão há herança e, SelectableChannelportanto, não pode ser gerenciado pelo seletor.

Processo de uso do seletor

  1. Obtenha a instância do seletor
  2. Registre o canal para o seletor
  3. Pesquisa de eventos IO prontos de interesse (um conjunto de teclas de seleção)

Modo reator reator

Qual é o modo do reator?

O modo de reator é composto de threads de reator de reator e processadores Manipuladores.

  • Responsabilidades do encadeamento do reator do reator: Responsável por responder a eventos de E / S e distribuído para o processador Handlers.
    Responsabilidades do processador: Execução sem bloqueio da lógica de negócios. Conclui o estabelecimento da conexão real, leitura do canal, processamento da lógica de negócios e responsável por gravar os resultados no canal.
    Insira a descrição da imagem aqui

Netty

O que é Netty

Netty é uma estrutura cliente-servidor baseada em NIO (NEW IO of Java), que pode ser usada para desenvolver aplicativos de rede de forma rápida e fácil.

O que há de tão bom no Netty?

O Netty é mais organizado do que o NIO que vem com o JDK.

  • Suporta vários protocolos, FTP, SMTP, HTTP e vários protocolos tradicionais binários e baseados em texto.
  • Modelo de threading simples e poderoso
  • Vem com vários codecs
  • Suporte para soquete de pacote sem conexão verdadeiro
  • Suporte total para SSL, / TLS e StartTLS
  • O ambiente da comunidade de desenvolvimento é bom e há muitas soluções de projeto de código aberto.

Componentes principais do Netty

  • Channel, A interface é uma classe abstrata do Netty para operações de rede. Inclui operações básicas de E / S, como bind (), connect (), read (), write (), etc.
    A classe de implementação mais comum é o servidor NioServerSocketChannel, NioSocketChannel (cliente).
  • EventLoop(事件循环)接口, O conceito central do Netty.主要作用实际就是负责监听网络事件并调用事件处理器进行相关 I/O 操作的处理。
  • ChannelFuture
    Netty é assíncrono e sem bloqueio, e todas as operações de E / S são assíncronas. E ChannelFuture é a solução assíncrona do Netty, por meio da qual você pode retornar o valor e saber se a operação foi executada com sucesso.

Registre um ChannelFutureListener por meio do método addListener () da interface ChannelFuture. Quando a operação for bem-sucedida ou falhar, o ouvinte acionará automaticamente o resultado de retorno.
E você também pode obter o canal associado por meio do método channel () de ChannelFuture

  • ChannelHandler: Processador específico de mensagem, responsável por operações de leitura e gravação, conexão de cliente, etc.

  • ChannelPipeline(通道流水线): Para a cadeia ChannelHandler, um contêiner é fornecido e APIs para propagar fluxos de eventos de entrada e saída ao longo da cadeia são definidos. 当 Channel 被创建时,它会被自动地分配到它专属的ChannelPipeline。Vários processadores Handler vinculados a um canal são adicionados a ele.
    ChannelPipline é projetado como uma lista duplamente vinculada, e o Handler é seu nó.

Qual é a forma de realização do uso do modo reator Reator no Netty?

O modo do reator do Reactor no Netty é refletido em:

  • Channel: Em primeiro lugar, embora o Netty não use diretamente o componente Canal do Java NIO, o Netty o encapsula para torná-lo adequado para vários protocolos, enquanto mantém IO assíncrono e IO bloqueador. A camada inferior do Canal encapsula a camada inferior do SelectableChannel.
  • Netty中的Reactor反应器: O nome do reator do Netty é: NioEventLoop. Sua função é semelhante à do reator do JavaNIO.Tem um thread de thread e uma pesquisa de eventos IO.
  • Netty中的Handler: O processador Handler da Netty é dividido em duas categorias, uma é o processador in-stack do canal ChannelInboundHandler e a segunda é o processador de saída do canal ChannelOutboundHandler. Todos herdados de ChannelHandler.

EventloopGroup entende? Qual é a relação com EventLoop?

  • O reator no Netty é um reator multithread. EventLoop é equivalente a um sub-reator. EventLoopGroup é o grupo de encadeamentos que gerencia esses sub-reatores.
  • Ao usar o Netty, o grupo de threads EventLoopGroup é usado em vez de um único EventLoop. Os parâmetros de construção de EventLoopGroup podem especificar o número de threads (o padrão é 2 vezes a CPU), e o número de threads corresponde a EventLoop um para um. Um EventLoop tem um thread dedicado para lidar com eventos de E / S. (Monitor, processador de chamadas)
    Insira a descrição da imagem aqui
    Como pode ser visto na figura acima: Quando o cliente se conecta ao servidor por meio do método de conexão, o bossGroup processa a solicitação de conexão do cliente. Quando o processamento do cliente for concluído, a conexão será enviada ao workerGroup para processamento e, em seguida, o workerGroup é responsável pelo processamento de suas operações relacionadas ao IO.

Você conhece Bootstrap e ServerBootstrap?

  • Bootstrap é a classe de inicialização / classe auxiliar do cliente
     EventLoopGroup group = new NioEventLoopGroup();
        try {
    
    
            //创建客户端启动引导/辅助类:Bootstrap
            Bootstrap b = new Bootstrap();
            //指定线程模型
            b.group(group).
                    ......
            // 尝试建立连接
            ChannelFuture f = b.connect(host, port).sync();
            f.channel().closeFuture().sync();
        } finally {
    
    
            // 优雅关闭相关线程组资源
            group.shutdownGracefully();
        }

O bootstrap geralmente usa o método connet () para se conectar a um host remoto e porta como um cliente na comunicação do protocolo TCP Netty. O bootstrap também pode vincular uma porta local por meio do método bind () como uma extremidade da comunicação do protocolo UDP.

  • Classe de inicialização de inicialização do lado do servidor ServerBootstrap / classe auxiliar
/1.创建线程反应组
//bossGroup 处理连接监听IO事件
//workerGroup 用于负责数据IO事件和Handler业务处理
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
    
    
            //.创建服务端启动引导/辅助类:ServerBootstrap
            ServerBootstrap b = new ServerBootstrap();
            //.给引导类配置两大线程组,确定了线程模型
            b.group(bossGroup, workerGroup).
            /2.设置通道的IO类型
            b.channel(NioServerSocketChannel.class)
            /3.设置监听端口
            b.localAddress(new InetSocketAddress(port))
            /4.设置通道传输参数
            b.option(给父通道接收连接通道设置的选项)
            /5.装配流水线
            b.pipeline().addLast(new Handler)
            / 6.绑定服务器新连接的端口号
            ChannelFuture f = b.bind(port).sync();
            // 等待连接关闭
            f.channel().closeFuture().sync();
        } finally {
    
    
            //7.优雅关闭相关线程组资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

O ServerBootstrap geralmente usa o método bind () para vincular à porta local e, em seguida, aguarda a conexão do cliente.

O Bootstrap só precisa configurar um grupo de thread - EventLoopGroup, enquanto o ServerBootstrap precisa configurar dois grupos de thread - EventLoopGroup, um para receber conexões e outro para processamento específico.

Quantos threads o construtor padrão de NioEventLoopGroup iniciará?

O padrão é CPU*2, mas pode ser alterado por meio do construtor.

Modelo de threading de Netty

No Netty, o pool de threads NioEventLoopGroup é usado principalmente para realizar o modelo de thread específico (modo de reator).

O modo Reactor é baseado em eventos orientados e usa multiplexação para distribuir eventos ao manipulador correspondente para processamento, o que é muito adequado para lidar com cenários de E / S massivos.

O que é TCP dip / unpack? Sua solução?

  • A colagem / descompactação do TCP ocorre quando você envia dados com base no TCP, várias strings são "coladas" juntas ou uma string é "desmontada".
  • O problema de mergulhar e descompactar no Netty: A capacidade de ler os dados subjacentes a cada vez é limitada.Quando o datagrama TCP subjacente é relativamente grande, um datagrama subjacente será empacotado e copiado, o que resultará em um meio pacote.
  • Quando o pacote de dados armazenado em buffer pela camada inferior do TCP é relativamente pequeno, ele é responsável por mais de um pacote de buffer do kernel por vez, fazendo com que o buffer do programa leia o pacote sujo.
  • Solução?
    (1) Você pode usar o decodificador fornecido pela Netty:
  1. LineBasedFrameDecoder: quando o remetente envia pacotes de dados, cada pacote de dados é separado por um caractere de nova linha. O princípio de funcionamento de LineBasedFrameDecoder é que ele percorre os bytes legíveis em ByteBuf por sua vez, determina se há um caractere de nova linha e, em seguida, executa a interceptação correspondente.
  2. DelimiterBasedFrameDecoder: você pode personalizar o decodificador do delimitador,
  3. LineBasedFrameDecoder é na verdade um decodificador DelimiterBasedFrameDecoder especial.
  4. FixedLengthFrameDecoder: decodificador de comprimento fixo, que pode descompactar a mensagem de acordo com o comprimento especificado.
  5. LengthFieldBasedFrameDecoder: decodificador de pacote de comprimento personalizado.
    (2) Empacotador de decodificador de serialização personalizado: como: serialização JSON.

Netty longa conexão

Sabemos que antes das leituras e gravações do TCP, uma conexão deve ser estabelecida com antecedência entre o servidor e o cliente. O processo de estabelecer uma conexão requer o aperto de mão de três vias que costumamos dizer, e quatro ondas de mãos são necessárias para liberar / fechar a conexão. Este processo consome recursos da rede e tem um atraso de tempo.
Portanto, o TCP usa uma conexão longa.

Mecanismo de batimento cardíaco de Netty

Várias condições anormais podem ocorrer no TCP em uma conexão longa, fazendo com que o servidor seja desconectado. Se não houver mecanismo de pulsação, o cliente não saberá que o servidor está inativo e, após a reinicialização do servidor, não saberá que o cliente pensou que ele estava conectado. Quando o cliente se desconecta acidentalmente, se o servidor não sabe que o TCP subjacente foi desconectado, a conexão se tornará uma conexão falsa, ocupando muitos recursos. Portanto, um mecanismo de pulsação é necessário para resolvê-lo.
Na verdade, o TCP vem com uma opção de conexão longa e também tem um mecanismo de pacote de pulsação, que é a opção de TCP: SO_KEEPALIVE. No entanto, a longa flexibilidade de conexão no nível do protocolo TCP não é suficiente. Portanto, em geral, implementamos um mecanismo de pulsação personalizado no protocolo da camada de aplicativo, ou seja, por meio de codificação no nível Netty. Se o mecanismo de pulsação for implementado por meio do Netty, a classe principal será IdleStateHandler.

Cópia zero de Netty

Cópia zero (inglês: cópia zero; também traduzido como cópia zero)

  • Tecnologia significa que quando o computador executa uma operação, a CPU não precisa primeiro copiar os dados de uma memória para outra área específica. Essa técnica geralmente é usada para economizar ciclos de CPU e largura de banda de memória ao transferir arquivos pela rede.
  • Da arquitetura de nível de sistema operacional, significa evitar a cópia de dados entre o modo de usuário e o modo kernel.

A cópia zero de Netty se reflete principalmente em:

  • Usando a classe CompositeByteBuf fornecida pelo Netty, vários ByteBufs podem ser mesclados em um ByteBuf lógico, evitando a cópia entre cada ByteBuf.
  • ByteBuf suporta operação de slice, então ByteBuf pode ser decomposto em vários ByteBuf compartilhando a mesma área de armazenamento, evitando cópia de memória.
  • A transferência de arquivos é realizada através de FileChannel.tranferTo empacotado por FileRegion, que pode enviar diretamente os dados do buffer de arquivo para o Canal de destino, evitando o problema de cópia de memória causado pelo método tradicional de escrita circular.

Acho que você gosta

Origin blog.csdn.net/H1517043456/article/details/107747970
Recomendado
Clasificación