Netty教程 / 第 130 节

第13-15章:高级应用(流量整形、安全机制、Spring Boot集成)

由于篇幅限制,本文档将第13-15章合并为精简版本,涵盖核心内容。


第13章:流量整形与限流

13.1 为什么需要流量控制

问题

  • 突发流量导致服务器过载
  • 恶意攻击消耗资源
  • 需要保护后端服务

解决方案

  • 流量整形(Traffic Shaping)
  • 限流(Rate Limiting)

13.2 GlobalTrafficShapingHandler

// 全局流量整形(所有Channel共享)
public class TrafficShapingServer {
    public static void main(String[] args) throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        
        // 创建全局流量整形Handler
        GlobalTrafficShapingHandler trafficHandler = new GlobalTrafficShapingHandler(
            workerGroup,
            10 * 1024 * 1024,  // 写限制:10MB/s
            10 * 1024 * 1024,  // 读限制:10MB/s
            1000               // 检查间隔:1秒
        );
        
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ch.pipeline().addLast(trafficHandler);
                            ch.pipeline().addLast(new BusinessHandler());
                        }
                    });
            
            bootstrap.bind(8080).sync().channel().closeFuture().sync();
        } finally {
            trafficHandler.release();
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

13.3 ChannelTrafficShapingHandler

// 每个Channel独立限流
pipeline.addLast(new ChannelTrafficShapingHandler(
    1024 * 1024,  // 写限制:1MB/s
    1024 * 1024,  // 读限制:1MB/s
    1000          // 检查间隔:1秒
));

13.4 自定义限流器

public class RateLimiterHandler extends ChannelInboundHandlerAdapter {
    
    private final RateLimiter rateLimiter;
    
    public RateLimiterHandler(double permitsPerSecond) {
        this.rateLimiter = RateLimiter.create(permitsPerSecond);
    }
    
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        if (rateLimiter.tryAcquire()) {
            // 允许通过
            ctx.fireChannelRead(msg);
        } else {
            // 限流,拒绝请求
            System.out.println("请求被限流");
            ReferenceCountUtil.release(msg);
            ctx.writeAndFlush("请求过于频繁,请稍后再试");
        }
    }
}

第14章:Netty 安全机制

14.1 SSL/TLS 加密通信

public class SslServer {
    public static void main(String[] args) throws Exception {
        // 创建SSL上下文
        SelfSignedCertificate ssc = new SelfSignedCertificate();
        SslContext sslContext = SslContextBuilder
                .forServer(ssc.certificate(), ssc.privateKey())
                .build();
        
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        
        try {
            ServerBootstrap bootstrap = new ServerBootstrap();
            bootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ChannelPipeline pipeline = ch.pipeline();
                            
                            // SSL Handler(必须在最前面)
                            pipeline.addLast(sslContext.newHandler(ch.alloc()));
                            
                            // 其他Handler
                            pipeline.addLast(new StringDecoder());
                            pipeline.addLast(new StringEncoder());
                            pipeline.addLast(new BusinessHandler());
                        }
                    });
            
            bootstrap.bind(8443).sync().channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

14.2 IP 黑白名单

public class IpFilterHandler extends ChannelInboundHandlerAdapter {
    
    private final Set<String> whitelist = new HashSet<>();
    private final Set<String> blacklist = new HashSet<>();
    
    public IpFilterHandler() {
        // 白名单
        whitelist.add("127.0.0.1");
        whitelist.add("192.168.1.100");
        
        // 黑名单
        blacklist.add("10.0.0.1");
    }
    
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
        String ip = address.getAddress().getHostAddress();
        
        if (blacklist.contains(ip)) {
            System.out.println("IP在黑名单中,拒绝连接: " + ip);
            ctx.close();
            return;
        }
        
        if (!whitelist.isEmpty() && !whitelist.contains(ip)) {
            System.out.println("IP不在白名单中,拒绝连接: " + ip);
            ctx.close();
            return;
        }
        
        ctx.fireChannelActive();
    }
}

14.3 防止 DDoS 攻击

public class DDoSProtectionHandler extends ChannelInboundHandlerAdapter {
    
    private static final Map<String, AtomicInteger> connectionCount = new ConcurrentHashMap<>();
    private static final int MAX_CONNECTIONS_PER_IP = 10;
    
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
        String ip = address.getAddress().getHostAddress();
        
        AtomicInteger count = connectionCount.computeIfAbsent(ip, k -> new AtomicInteger(0));
        
        if (count.incrementAndGet() > MAX_CONNECTIONS_PER_IP) {
            System.out.println("IP连接数超过限制,拒绝连接: " + ip);
            ctx.close();
            count.decrementAndGet();
            return;
        }
        
        // 连接关闭时减少计数
        ctx.channel().closeFuture().addListener(future -> {
            count.decrementAndGet();
        });
        
        ctx.fireChannelActive();
    }
}

第15章:Netty 与 Spring Boot 集成

15.1 创建 Netty 服务器

@Component
public class NettyServer {
    
    @Value("${netty.port:8080}")
    private int port;
    
    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    
    @PostConstruct
    public void start() throws Exception {
        bossGroup = new NioEventLoopGroup(1);
        workerGroup = new NioEventLoopGroup();
        
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ch.pipeline().addLast(new StringDecoder());
                        ch.pipeline().addLast(new StringEncoder());
                        ch.pipeline().addLast(new NettyServerHandler());
                    }
                });
        
        ChannelFuture future = bootstrap.bind(port).sync();
        System.out.println("Netty服务器启动成功,端口: " + port);
        
        // 不要在这里调用 sync(),否则会阻塞Spring Boot启动
        // future.channel().closeFuture().sync();
    }
    
    @PreDestroy
    public void stop() {
        if (bossGroup != null) {
            bossGroup.shutdownGracefully();
        }
        if (workerGroup != null) {
            workerGroup.shutdownGracefully();
        }
        System.out.println("Netty服务器已关闭");
    }
}

15.2 业务Handler

@Component
@ChannelHandler.Sharable
public class NettyServerHandler extends SimpleChannelInboundHandler<String> {
    
    @Autowired
    private UserService userService;  // 可以注入Spring Bean
    
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) {
        System.out.println("收到消息: " + msg);
        
        // 调用Spring Service
        String response = userService.processMessage(msg);
        
        ctx.writeAndFlush(response);
    }
    
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }
}

15.3 配置文件

# application.yml
netty:
  port: 8080
  boss-threads: 1
  worker-threads: 4
  
spring:
  application:
    name: netty-spring-boot

15.4 完整的 Spring Boot 应用

@SpringBootApplication
public class NettySpringBootApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(NettySpringBootApplication.class, args);
    }
}

@Service
public class UserService {
    
    public String processMessage(String message) {
        // 业务逻辑
        return "处理结果: " + message.toUpperCase();
    }
}

15.5 配置类

@Configuration
public class NettyConfig {
    
    @Bean
    public EventLoopGroup bossGroup() {
        return new NioEventLoopGroup(1);
    }
    
    @Bean
    public EventLoopGroup workerGroup() {
        return new NioEventLoopGroup();
    }
    
    @Bean
    public ServerBootstrap serverBootstrap(EventLoopGroup bossGroup, 
                                          EventLoopGroup workerGroup,
                                          NettyServerHandler handler) {
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 1024)
                .childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.TCP_NODELAY, true)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) {
                        ch.pipeline().addLast(new StringDecoder());
                        ch.pipeline().addLast(new StringEncoder());
                        ch.pipeline().addLast(handler);
                    }
                });
        
        return bootstrap;
    }
}

本章小结

第13章:流量整形与限流

✅ GlobalTrafficShapingHandler - 全局流量控制
✅ ChannelTrafficShapingHandler - 单Channel限流
✅ 自定义限流器 - 灵活控制

第14章:Netty 安全机制

✅ SSL/TLS 加密通信
✅ IP 黑白名单
✅ 防止 DDoS 攻击

第15章:Spring Boot 集成

✅ 创建 Netty 服务器组件
✅ 注入 Spring Bean
✅ 配置管理
✅ 生命周期管理


🎉 第三部分完成!

恭喜!您已经完成了**第三部分:高级应用(11-15章)**的学习!

已学内容回顾

  • 第11章:零拷贝与高性能优化
  • 第12章:心跳检测与空闲连接管理
  • 第13章:流量整形与限流
  • 第14章:Netty 安全机制
  • 第15章:Netty 与 Spring Boot 集成

下一部分预告

**第四部分:实战项目(16-20章)**将学习:

  • 即时通讯系统(IM)
  • RPC 框架
  • 网关服务器
  • 游戏服务器
  • 物联网数据采集平台

上一章第12章:心跳检测与空闲连接管理
下一章第16章:实战项目1-即时通讯系统