zoukankan      html  css  js  c++  java
  • 在netty decoder层控制heap内存占用,防止es oom

    es使用netty来通信,实现分布式的功能,但在某些场景会oom。

    1:netty概述
    IO 多路复用
    NioEventLoop.run select由jdk实现在win下使用select,在linux下使用epoll。
    linux下也可以使用netty实现的epoll:EpollEventLoop。

    线程模型
    parent NioEventLoop[listen] [1]---- [n] children NioEventLoop[established] [1]----[n] channel [1]---- [1] channelPipeline[channelInboud/Outboundhandler list]。
    1:每个NioEventLoop绑定一个线程。
    2:parent NioEventLoop负责监听连接请求,并将建立连接请求轮询分配给childrenNioEventLoop。
    3:一个child NioEventLoop通过select/epoll处理所负责的N个channels上的read,write事件。且一个channel上的read,write事件只能在该NioEventLoop线程上处理,并发安全。
    4:具体处理时,由该channel对应的channelPipeline中的各个channelHandler顺序处理。

    2:es对netty的使用
    TCP/IP
    1:一个request/response可能会因为分包(最大64k),对应产生多次channelRead/write。
    2:一个数据包channelRead也可能因为tcp的延迟发送(粘包),而包括多个request,或者一个request的后半部分和下一个request的前半部分。
    3:所以在channelPipeline中处理channelRead的数据包时,需要累积多个数据包数据组成一个完整的request,或者从一个数据包中拆分出多个request。

    引起oom
    当多个size很大的request,使用不同的channel,发送到不同的NioEventLoop处理时。

    由于需要累积完整的数据包,才能交给下一个handler去反序列化成对象,进而处理请求。所以,多个channel中累计部分的request的数据时,可能会引起oom。

    相关代码:
    ByteToMessageDecoder
    Netty4SizeHeaderFrameDecoder
    Netty4MessageChannelHandler
    Netty4Transport
    TcpTransport

    3:限流实现避免oom
    增加总的计数器(breaker),读取request的第一个数据包,从中header中读取request的size,如果超过limit限制,则舍弃该request的本次,及后续的所有数据包。
    注意
    1:request的第一个数据包可能在一个新包的开头。也可能因为延迟发送,和其他request在一个数据包中。
    2:累加器如果成功加上,则要读取完整size的request后,交给es处理请求,并保证处理后减去size。累加器如果超过limit,则需要从多个数据包中,舍弃size长度的数据,并交给es处理shardFailure。
    3:可以设置request的status,指定只对某些大的结果(如:聚合)做限流。

  • 相关阅读:
    asp.net(C#)利用QRCode生成二维码(续)-在二维码图片中心加Logo或图像
    C#中DataTable中的Compute方法使用收集
    c#的DateTime.Now函数详解
    附加数据库失败,拒绝访问
    xml文件绑定chenckbox选择框
    Maximum Xor Secondary(单调栈好题)
    Y(类树形DP)
    Average distance(类树形DP)
    Balls and Boxes (模拟题)
    Party at Hali-Bula(树形DP+判断方案数是否唯一)
  • 原文地址:https://www.cnblogs.com/vsop/p/12703618.html
Copyright © 2011-2022 走看看