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 框架
- 网关服务器
- 游戏服务器
- 物联网数据采集平台