频繁的完整GC的apache风暴

时间:2016-03-13 07:19:36

标签: memory garbage-collection jvm apache-kafka apache-storm

风暴0.9.6

Worker JVM args:

Config.TOPOLOGY_WORKER_CHILDOPTS: "-Xmx4096m -Xss256k -XX:MaxDirectMemorySize=4096m -XX:PermSize=512m "

通过StoppableKafkaSpout读取数据。然后我尝试解析每个输入行。

计数器功能:

    AtomicLong ct_in = new AtomicLong(0L);
    public void countIn(){
      long cin = ct_in.getAndIncrement();
      if(cin % 100000 == 0){
        System.err.println("[x] reading." + Thread.currentThread() + " count:" + cin);
      }
    }

第一个测试代码:不做任何事情只计算:

    public void parse(String line) {
      countIn();
      if(true){ // 
        return;
      }
      // nothing to do...
    }

第一个gc信息和输出:

$ jstat -gcutil 15510 1000 500

    S0     S1     E      O      M     CCS    YGC     YGCT    FGC    FGCT     GCT   

    0.00   0.49  64.44   6.26  97.61  95.35    217    1.144     2    0.118    1.262

    0.00   5.78  46.35   6.26  97.61  95.35    219    1.152     2    0.118    1.270

    0.00   7.82  38.42   6.26  97.61  95.35    221    1.160     2    0.118    1.278

    0.00   6.45  16.13   6.26  97.61  95.35    223    1.168     2    0.118    1.286

    4.80   0.00  82.64   6.26  97.61  95.35    224    1.171     2    0.118    1.290

    1.39   0.00  59.54   6.26  97.61  95.35    226    1.180     2    0.118    1.299

    1.02   0.00  39.77   6.26  97.61  95.35    228    1.188     2    0.118    1.307

    0.00   6.22  91.23   6.26  97.61  95.35    229    1.193     2    0.118    1.311

    0.00   1.17  81.15   6.26  97.64  95.38    231    1.202     2    0.118    1.320

    0.00   3.23  59.05   6.26  97.64  95.38    233    1.210     2    0.118    1.329

    0.00   2.57  50.69   6.26  97.64  95.38    235    1.219     2    0.118    1.337

    0.00   0.54  13.92   6.26  97.64  95.38    237    1.227     2    0.118    1.345

    0.31   0.00  86.84   6.26  97.64  95.38    238    1.230     2    0.118    1.348

    0.00   0.17  99.73   6.26  97.64  95.38    239    1.234     2    0.118    1.352

    0.38   0.00  87.92   6.26  97.64  95.38    240    1.239     2    0.118    1.357

    1.34   0.00  37.79   6.26  97.65  95.38    242    1.246     2    0.118    1.364

    0.63   0.00   0.00   6.26  97.65  95.38    244    1.258     2    0.118    1.377

    0.00   0.35  50.55   6.26  97.65  95.38    245    1.263     2    0.118    1.381

    0.00   1.36   0.00   6.26  97.66  95.38    247    1.269     2    0.118    1.387

    6.27   0.00  64.02   6.26  97.66  95.38    248    1.273     2    0.118    1.391

    5.71   0.00  61.99   6.26  97.66  95.38    250    1.281     2    0.118    1.399

    3.32   0.00  69.13   6.26  97.67  95.38    252    1.288     2    0.118    1.407

    6.17   0.00  36.57   6.26  97.69  95.38    254    1.296     2    0.118    1.415

    5.74   0.00   5.70   6.26  97.71  95.38    256    1.305     2    0.118    1.423

    0.00  11.27  84.73   6.26  97.71  95.38    257    1.310     2    0.118    1.428

    0.00   9.28  91.32   6.26  97.71  95.38    259    1.318     2    0.118    1.436

    0.00   3.21  78.01   6.26  97.71  95.38    261    1.326     2    0.118    1.445

    0.00  19.92  71.34   6.26  97.71  95.38    263    1.336     2    0.118    1.455

    0.00   3.44  40.88   6.26  97.72  95.38    265    1.345     2    0.118    1.463

    0.00  10.53  34.00   6.26  97.72  95.38    267    1.352     2    0.118    1.470

    0.00   1.12   6.22   6.26  97.73  95.38    269    1.360     2    0.118    1.478

    0.50   0.00  91.07   6.26  97.73  95.38    270    1.364     2    0.118    1.482

    3.10   0.00  97.11   6.26  97.73  95.38    272    1.372     2    0.118    1.490

    11.48   0.00  89.29   6.26  97.73  95.38    274    1.383     2    0.118    1.502

    12.19   0.00  78.67   6.26  97.73  95.38    276    1.393     2    0.118    1.511

    6.01   0.00  53.11   6.26  97.73  95.38    278    1.400     2    0.118    1.518

    0.81   0.00   4.09   6.26  97.73  95.38    280    1.409     2    0.118    1.527

    0.00   8.06  76.45   6.26  97.73  95.38    281    1.414     2    0.118    1.533

输出:

.........
2016-03-13T14:28:14.926+0800 STDIO [ERROR] [x] reading.Thread[Thread-5-parser,5,main] count:40900000
2016-03-13T14:28:15.465+0800 STDIO [ERROR] [x] reading.Thread[Thread-5-parser,5,main] count:41000000
2016-03-13T14:28:16.019+0800 STDIO [ERROR] [x] reading.Thread[Thread-5-parser,5,main] count:41100000
2016-03-13T14:28:16.501+0800 STDIO [ERROR] [x] reading.Thread[Thread-5-parser,5,main] count:41200000
2016-03-13T14:28:17.003+0800 STDIO [ERROR] [x] reading.Thread[Thread-5-parser,5,main] count:41300000
2016-03-13T14:28:17.542+0800 STDIO [ERROR] [x] reading.Thread[Thread-5-parser,5,main] count:41400000

您可以看到它正常工作,并处理了超过40000000行。

第二段代码:我刚刚添加了split()操作:

    public void parse(String line) {
      countIn();
      if(true){ // 
      }
      String[] fields = line.trim().split("\t"); // the only operation
      if(true){
        return;
      }
    }

第二个gc信息:

      ................        
      0.00 100.00   0.00  81.59  98.00  96.71    277    9.968    38    1.224   11.193

      0.00 100.00  44.39  78.65  98.00  96.71    279   10.067    38    1.224   11.291

    100.00   0.00   0.00  81.76  98.01  96.71    282   10.170    38    1.224   11.394

    100.00   0.00  55.90  85.37  98.01  96.71    284   10.264    38    1.224   11.488

      0.00 100.00   0.00  90.49  98.06  96.71    287   10.404    39    1.228   11.632

      0.00 100.00  55.95  93.95  98.06  96.71    289   10.503    40    1.261   11.764

      0.00 100.00  96.74  83.56  98.06  96.71    292   10.605    40    1.261   11.866

     96.69   0.00  49.89  87.89  98.06  96.71    294   10.729    40    1.261   11.990

      0.00 100.00  22.86  91.05  98.06  96.71    297   10.830    41    1.264   12.094

      0.00 100.00  69.56  94.34  98.08  96.71    299   10.908    41    1.264   12.172

     81.73  93.15 100.00  85.74  98.08  96.71    302   10.983    42    1.311   12.294

     96.22   0.00  79.59  88.45  98.08  96.71    304   11.086    42    1.311   12.397

      0.00 100.00  51.37  92.46  98.08  96.71    307   11.185    44    1.315   12.500

     84.06   0.00   3.87  88.05  98.08  96.71    310   11.291    44    1.360   12.650

    100.00   0.00  82.37  89.45  98.08  96.71    312   11.332    44    1.360   12.692

      0.00 100.00  38.60  94.44  98.10  96.71    315   11.460    45    1.363   12.823

      0.00 100.00  72.97  88.06  98.10  96.71    317   11.533    46    1.389   12.922

    100.00   0.00   3.99  92.62  98.10  96.71    320   11.645    47    1.393   13.038

     95.22   0.00  81.26  90.02  98.10  96.71    322   11.712    48    1.452   13.164

      0.00 100.00  41.85  94.77  98.10  96.71    325   11.832    49    1.455   13.287

     95.03   0.00   0.00  93.60  98.10  96.71    328   11.946    50    1.509   13.455

完整的GC一次又一次地获得支持。

输出:

2016-03-13T15:00:44.119+0800 STDIO [ERROR] [x] reading.Thread[Thread-5-parser,5,main] count:24900000
2016-03-13T15:00:52.117+0800 STDIO [ERROR] [x] reading.Thread[Thread-5-parser,5,main] count:25000000

然后工作线程因Full GC而被阻止......

JVM gc log:

2016-03-13T15:01:15.380+0800: 238.646: Total time for which application threads were stopped: 0.1699727 seconds, Stopping threads took: 0.0000422 seconds
2016-03-13T15:01:15.380+0800: 238.646: [CMS-concurrent-mark-start]
2016-03-13T15:01:15.483+0800: 238.748: [Full GC (Allocation Failure) 238.748: [CMS2016-03-13T15:01:16.055+0800: 239.320: [CMS-concurrent-mark: 0.673/0.674 secs] [Times: user=1.65 sys=0.03, real=0.68 secs] 

jmap log:

$ jmap -histo xxxx | head                       
  num     #instances         #bytes  class name
  ----------------------------------------------
  1:       5971981     3189464624  [B
  2:       5945371      142688904  backtype.storm.messaging.TaskMessage
  3:        359549       38503840  [Ljava.lang.Object;
  4:          1808       31499496  [I
  5:         65226        7823656  [C
  6:        301860        7244640  java.util.ArrayList
  7:        294871        7076904 java.util.concurrent.LinkedBlockingQueue$Node

所以,问题是,为什么只有一行代码

line.trim().split();

造成如此大的差异?如果我不能使用String.split(以及其他一些API,如StringBuilder,那么处理从KafkaSpout读取的行的正确方法是什么。他们也遇到了同样的问题)......

2 个答案:

答案 0 :(得分:4)

你的幸存者空间正在填满。如果您的幸存者空间不足以获取次要集合上的所有数据,则会触发完整集合。尝试增加幸存者空间的大小,使它们永远不会填满。

在幸存者空间达到8%之前

0.00   7.82  38.42   6.26  97.61  95.35    221    1.160     2    0.118    1.278

你的幸存者空间达到100%之后。

  0.00 100.00   0.00  81.59  98.00  96.71    277    9.968    38    1.224   11.193

  0.00 100.00  44.39  78.65  98.00  96.71    279   10.067    38    1.224   11.291

100.00   0.00   0.00  81.76  98.01  96.71    282   10.170    38    1.224   11.394

100.00   0.00  55.90  85.37  98.01  96.71    284   10.264    38    1.224   11.488

虽然你的手术看起来足够无害,但如果你的幸存者空间不够大,它仍然可以将它吹灭。即你正在创造许多中等生命的物体,这些物体总是存在问题。

我会尝试增加最大堆大小,这对于你的新代码来说似乎太长了,并且会增加你的年轻代。

-Xmx8g -Xmn4g

答案 1 :(得分:0)

最有可能的是,导致它的并行螺栓的数量 或storm.yaml中的风暴设置和拓扑提交配置。 尝试将CPU消耗螺栓的数量设置为核心数量。

并尝试增加堆的最小大小: -Xms4G