netty-安全增强,防止OOM,空闲检测,黑白名单设置

netty防止出现OOM

  • netty oom出现原因:
    • 根源在于读的速度大于写的速度
  • netty 防止oom对策:
    • 设置netty高低水位线
    • 启动流量整形时考虑:1.maxwrite(默认4m) 2.maxGlobalWriteSize(默认400M) 3.maxWriteDelay(默认4s)
    • 修改程序:在handler里面写之前判断是否可写,如果不可写就做另外处理
public class BussinessProcessHandler extends SimpleChannelInboundHandler<Object> {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if(ctx.channel().isActive()&&ctx.channel().isWritable()){
            ctx.writeAndFlush(new Object());
        }else {
            System.out.println("message drop");
        }
    }

netty开启空闲检测

  • 为了防止某些client长期占用连接,而不发送数据,netty可以开启空闲检测
    • 服务器加上read idle check 服务器10s接收不到channel的请求就断开连接,实现:1.继承Netty的IdleStateHandler,
public class ServerIdleCheckHandler extends IdleStateHandler {
    public ServerIdleCheckHandler(int readerIdleTimeSeconds, int writerIdleTimeSeconds, int allIdleTimeSeconds) {
        super(readerIdleTimeSeconds, writerIdleTimeSeconds, allIdleTimeSeconds);
    }

    @Override
    protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception {
        if(evt==IdleStateEvent.FIRST_READER_IDLE_STATE_EVENT){
            ctx.close();
            return;
        }
        super.channelIdle(ctx, evt);
    }
}

2.添加到PipeLine中,第一个参数为10s未发生读事件

socketChannel.pipeline().addLast("serverIdleHandler",new ServerIdleCheckHandler(10,
                                0,0));

3.当事件发生后,将会触发ServerIdleCheckHandler 的事件:

//在这里判断是否是第一次触发,如果是第一次触发就关闭连接
  protected void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception {
        if(evt==IdleStateEvent.FIRST_READER_IDLE_STATE_EVENT){
            ctx.close();
            return;
        }
        super.channelIdle(ctx, evt);
    }
  • 客户端write idle check +keepalive 客户端5s不发生数据就发一个keepalive,避免被断开,启用不频繁的keepalive。实现:1.同样创建一个Idle 继承自IdleStateHandler
public class ClientIdleCheckHandler extends IdleStateHandler {
    public ClientIdleCheckHandler(int readerIdleTimeSeconds, int writerIdleTimeSeconds, int allIdleTimeSeconds) {
        super(readerIdleTimeSeconds, writerIdleTimeSeconds, allIdleTimeSeconds);
    }
}

2.我们创建一个单独的handler来处理发送心跳包

public class KeepaliveHandler extends ChannelDuplexHandler {
    @Override
    //在userEventTriggered方法中触发发送心挑包
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if(evt== IdleStateEvent.FIRST_WRITER_IDLE_STATE_EVENT){
            System.out.println("发送心跳包");
            ctx.writeAndFlush(new Object());
        }
        super.userEventTriggered(ctx, evt);
    }
}

netty 黑白名单

  • netty的"cidrPrefix":
    理解cidr就需要理解子网掩码 ,这边导入知乎大神的讲解如何理解子网掩码
  • netty 地址过滤:
    • 同一个ip只能有一个连接:实现
  //创建handler,该handler用于处理同一个ip只限一个连接
  UniqueIpFilter filter=new UniqueIpFilter();
  //加入pipeline
  socketChannel.pipeline().addLast(filter);
- ip地址过滤:黑名单,白名单,实现:比如这边禁止192.168.1.0-192.168.1.63 的ip连接
//这边的cidrPrefix网络号为26
IpSubnetFilterRule subnetFilterRule=new IpSubnetFilterRule("192.168.1.0",26,IpFilterRuleType.REJECT);
                        RuleBasedIpFilter ipFilter= new RuleBasedIpFilter();
                        socketChannel.pipeline().addLast("ipFilter",ipFilter);

你可能感兴趣的:(java)