SpringBoot 는 Netty 를 사용 하여 원 격 호출 을 실현 하 는 예제 입 니 다.

머리말
알다 시 피 우리 가 네트워크 연결 을 할 때 소켓 연결 을 구축 하 는 것 은 매우 성능 을 소모 하 는 일이 다.특히 분포 식 상황 에서 스 레 드 풀 로 여러 클 라 이언 트 연결 을 유지 하 는 것 은 스 레 드 를 매우 소모 하 는 행위 이다.그렇다면 우 리 는 어떤 기술 을 통 해 상술 한 문 제 를 해결 해 야 합 니까?그러면 네트워크 연결 의 이기 인Netty을 제기 해 야 합 니까?
본문 Netty
Netty 는NIO클 라 이언 트 서버 프레임 워 크 입 니 다.
  • 프로 토 콜 서버 와 클 라 이언 트 등 네트워크 응용 프로그램 을 신속하게 개발 할 수 있 습 니 다.
  • 이 는 네트워크 프로 그래 밍 을 크게 간소화 하고 간소화 했다.예 를 들 어TCPUDP소켓 서버 등 이다.
  • NIO는 비 차단IO으로 다음 과 같은 특징 을 가진다.
  • 단일 스 레 드 는 여러 클 라 이언 트 를 연결 할 수 있 습 니 다.
  • 선택 기 는 실현 할 수 있 지만 스 레 드 관리 여러 개Channel,새로운 채널 은 모두 선택 기 에 등록 해 야 합 니 다.
  • 하나의SelectionKey키 는 특정한 채널 대상 과 특정한 선택 기 대상 간 의 등록 관 계 를 나타 낸다.
  • selector작업 을 하면 차단 이 생 길 수 있 지만 차단 시간 을 설정 할 수 있 고select()로 깨 울 수 있 기 때문에wakeup()시비 차단selector
  • Netty 모델 선택 기 모드
    그것 은 일반NIO에 비해 성능 이 향상 되 었 고 사용 되 었 다.
  • IO다 중 스 레 드 방식 으로 여러 개NIO
  • 를 동시에 사용 할 수 있다.
  • 여러 포트 를 연결 하 는 방식 으로 한 개NIO가 여러 개selector
  • 를 동시에 등록 할 수 있 도록 한다.
  • 단일 스 레 드 에서 한 개selector만 있 을 수 있 고ServerSocketServer의 일치 와 재 활용 을 실현 할 수 있다.
  • 在这里插入图片描述
    문제selector메 시 지 를 보 낼 때 가방 을 뜯 을 수 있 기 때문에 수신 자 는 언제 받 은 데이터 가 완전한 데이터 인지 알 수 없다.전통 적 인Channel에서 데 이 터 를 읽 지 못 할 때 차단 이 발생 하지만TCP/IP그렇지 않 습 니 다.BIO의 패키지 문 제 를 해결 하기 위해NIO모델 을 바탕 으로NIO모델 을 제시 하여 클 라 이언 트 가 서버 에서 불완전 하 게 요구 하 는 문 제 를 해결 했다.
    netty 모델 reactor 모드Netty을 바탕 으로 반 가방 문 제 를 해결 했다.
    在这里插入图片描述
    위의 그림 은 간단하게'boss 가 일 을 맡 고 work 를 하 게 합 니 다'라 고 묘사 할 수 있 습 니 다.Selector요청 을 받 는 데 사 용 됩 니 다(클 라 이언 트 와 악수 검증 을 할 것 입 니 다).reactor요청 을 처리 하 는 데 사 용 됩 니 다(클 라 이언 트 와 직접 연결 하지 않 습 니 다).
    SpringBoot 는 Netty 를 사용 하여 원 격 호출 을 실현 합 니 다.
    maven 의존
    
    <!--lombok-->
    <dependency>
     <groupId>org.projectlombok</groupId>
     <artifactId>lombok</artifactId>
     <version>1.18.2</version>
     <optional>true</optional>
    </dependency>
    
    <!--netty-->
    <dependency>
     <groupId>io.netty</groupId>
     <artifactId>netty-all</artifactId>
     <version>4.1.17.Final</version>
    </dependency>
    
    서버 부분
    NettyServer.java:서비스 시작 모니터
    
    @Slf4j
    public class NettyServer {
      public void start() {
        InetSocketAddress socketAddress = new InetSocketAddress("127.0.0.1", 8082);
        //new       
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        //new        
        EventLoopGroup workGroup = new NioEventLoopGroup(200);
        ServerBootstrap bootstrap = new ServerBootstrap()
            .group(bossGroup, workGroup)
            .channel(NioServerSocketChannel.class)
            .childHandler(new ServerChannelInitializer())
            .localAddress(socketAddress)
            //      
            .option(ChannelOption.SO_BACKLOG, 1024)
            //             ,TCP               
            .childOption(ChannelOption.SO_KEEPALIVE, true);
        //    ,         
        try {
          ChannelFuture future = bootstrap.bind(socketAddress).sync();
          log.info("           : {}", socketAddress.getPort());
          future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
          log.error("       ", e);
        } finally {
          //      
          bossGroup.shutdownGracefully();
          //       
          workGroup.shutdownGracefully();
        }
      }
    }
    
    ServerChannel Initializer.java:selector서비스 초기 화 기
    
    /**
    * netty      
    **/
    public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
      @Override
      protected void initChannel(SocketChannel socketChannel) throws Exception {
        //     
        socketChannel.pipeline().addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
        socketChannel.pipeline().addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
        socketChannel.pipeline().addLast(new NettyServerHandler());
      }
    }
    NettyServerHandler.java:manReactor서버 프로세서
    
    /**
    * netty      
    **/
    @Slf4j
    public class NettyServerHandler extends ChannelInboundHandlerAdapter {
      /**
       *         
       */
      @Override
      public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("Channel active......");
      }
    
      /**
       *          
       */
      @Override
      public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        log.info("       : {}", msg.toString());
        ctx.write("    ");
        ctx.flush();
      }
    
    
      /**
       *       
       */
      @Override
      public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
      }
    }
    
    RpcServerApp.java:subReactor시작 클래스
    
    /**
    *    
    *
    */
    @Slf4j
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
    public class RpcServerApp extends SpringBootServletInitializer {
      @Override
      protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(RpcServerApp.class);
      }
    
      /**
       *        
       *
       * @param args
       */
      public static void main(String[] args) {
        SpringApplication.run(RpcServerApp.class, args);
        //  Netty  
        NettyServer nettyServer =new NettyServer ();
        nettyServer.start();
        log.info("======      ========");
      }
    }
    
    클 라 이언 트 부분
    NettyClient Util.java:netty도구 클래스
    
    /**
    * Netty   
    **/
    @Slf4j
    public class NettyClientUtil {
    
      public static ResponseResult helloNetty(String msg) {
        NettyClientHandler nettyClientHandler = new NettyClientHandler();
        EventLoopGroup group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap()
            .group(group)
            //            Nagle  ,          
            .option(ChannelOption.TCP_NODELAY, true)
            .channel(NioSocketChannel.class)
            .handler(new ChannelInitializer<SocketChannel>() {
              @Override
              protected void initChannel(SocketChannel socketChannel) throws Exception {
                socketChannel.pipeline().addLast("decoder", new StringDecoder());
                socketChannel.pipeline().addLast("encoder", new StringEncoder());
                socketChannel.pipeline().addLast(nettyClientHandler);
              }
            });
        try {
          ChannelFuture future = bootstrap.connect("127.0.0.1", 8082).sync();
          log.info("       ....");
          //    
          future.channel().writeAndFlush(msg);
          //        
          future.channel().closeFuture().sync();
          return nettyClientHandler.getResponseResult();
        } catch (Exception e) {
          log.error("   Netty  ", e);
          throw new BusinessException(CouponTypeEnum.OPERATE_ERROR);
        } finally {
          //              
          group.shutdownGracefully();
        }
      }
    }
    
    NettyClient Handler.java:클 라 이언 트 프로세서
    
    /**
    *       
    **/
    @Slf4j
    @Setter
    @Getter
    public class NettyClientHandler extends ChannelInboundHandlerAdapter {
    
      private ResponseResult responseResult;
    
      @Override
      public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("   Active .....");
      }
    
      @Override
      public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        log.info("       : {}", msg.toString());
        this.responseResult = ResponseResult.success(msg.toString(), CouponTypeEnum.OPERATE_SUCCESS.getCouponTypeDesc());
        ctx.close();
      }
    
      @Override
      public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
      }
    }
    
    검증 하 다.
    테스트 인터페이스
    
    @RestController
    @Slf4j
    public class UserController {
    
      @PostMapping("/helloNetty")
      @MethodLogPrint
      public ResponseResult helloNetty(@RequestParam String msg) {
        return NettyClientUtil.helloNetty(msg);
      }
    }
    
    액세스 테스트 인터페이스
    在这里插入图片描述
    서버 인쇄 정보
    在这里插入图片描述
    클 라 이언 트 인쇄 정보
    在这里插入图片描述
    소스 코드
    프로젝트 원본 코드 는 나의 github 에서 가 져 올 수 있 습 니 다:github 소스 주소
    여기 서 SpringBoot 가 Netty 를 사용 하여 원 격 호출 을 실현 하 는 예제 에 관 한 글 은 여기까지 소개 되 었 습 니 다.더 많은 SpringBoot Netty 원 격 호출 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 바 랍 니 다!

    좋은 웹페이지 즐겨찾기