카테고리 없음

spring과 netty

머룽 2023. 4. 19. 09:55
이번엔 spring을 이용해서 netty의 서버를 만들어보자 내용은 비슷하다. 기존에 했던거와 비슷하다. 스프링의 설정만 사용했다. main부터 보자
  public static void main(String[] args) {
    try(AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class)){
      context.registerShutdownHook();
      NettyServer nettyServer = context.getBean(NettyServer.class);
      nettyServer.start();
    }
  }
다들 아시다 시피 AnnotationConfigApplicationContext 에 SpringConfig을 설정했다. 다음 으로 SpringConfig를 보자
@Configuration
@ComponentScan("me.wonwoo.spring")
@PropertySource("classpath:server.properties")
@Getter
public class SpringConfig {

  @Value("${tcp.port}")
  private int port;

  @Bean
  public InetSocketAddress tcpPort() {
    return new InetSocketAddress(port);
  }

  @Bean
  public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
    return new PropertySourcesPlaceholderConfigurer();
  }
}

이거 역시 스프링을 할 줄 아는 사람이라면 다 아는 내용이다. 젠장 딱히 할 얘기가 없네.. 다음으로는 NettyServer를 보자 실제 netty의 서버를 올리는 곳이다.
@Component
public class NettyServer {

  @Value("${boss.thread.count}")
  private int bossCount;

  @Value("${worker.thread.count}")
  private int workerCount;

  @Autowired
  private InetSocketAddress port;

  private static final ServiceHandler SERVICE_HANDLER = new ServiceHandler();

  public void start() {
    EventLoopGroup bossGroup = new NioEventLoopGroup(bossCount);
    EventLoopGroup workerGroup = new NioEventLoopGroup(workerCount);

    try {
      ServerBootstrap b = new ServerBootstrap();
      b.group(bossGroup, workerGroup)
        .channel(NioServerSocketChannel.class)
        .childHandler(new ChannelInitializer<SocketChannel>() {
          @Override
          protected void initChannel(SocketChannel ch) throws Exception {
            ChannelPipeline pipeline = ch.pipeline();
            pipeline.addLast(SERVICE_HANDLER);
          }
        });

      ChannelFuture channelFuture = b.bind(port).sync();
      channelFuture.channel().closeFuture().sync();
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      bossGroup.shutdownGracefully();
      workerGroup.shutdownGracefully();
    }
  }
}

여기 역시 할얘기가 딱히 없다. NettyServer를 스프링의 빈으로 설정 했다. 그래야 Context에 저 아이가 있다. 다음으로는 handler를 보자
@ChannelHandler.Sharable
public class ServiceHandler extends ChannelInboundHandlerAdapter {

  Logger logger = LoggerFactory.getLogger(this.getClass());

  private final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

  @Override
  public void channelActive(ChannelHandlerContext ctx) throws Exception {
    channels.add(ctx.channel());
  }

  @Override
  public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    ByteBuf byteBuf = (ByteBuf) msg;
    logger.debug("message : {} ",byteBuf.toString(Charset.defaultCharset()));
    channels.writeAndFlush(msg);
  }
}

이제부터는 완전 netty다 우리가 이제껏 배워온 네티다. 한번 텔넷으로 접속을 해보자. 채팅을 할 수 있게 만들었다. 에코서버는 너무 식상하니까. 아마두 잘 돌아 갈 것으로 예상된다. spring과 함께 API서버도 만들 수 있다. 혹은 어떤 사람이 Spring Boot에 내장 서버로 Netty를 구현한 것도 있다. https://github.com/DanielThomas/spring-boot-starter-netty.git 이것으로 netty는 모두 마치겠다. vertx도 해야되는데.. 흠흠