1. Environment
OS: CentOS Linux release 7.8.2003 (Core)

JDK: java version "1.8.0_181"
Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)

Tomcat: tomcat-embed-core-8.5.32 with spring-boot-2.0.4-RELEASE

2. Reproduce Steps

1. request large data download api, then request 2000+ request to
another lightweight api
2. the system now is Full GC, and the 2000+ request will blocked, then
close all these request
3. after system throw OufOfMemoryError, the memory will be released, the
cpu and memory  occupation is normal, the system is ok to visit mysql
database and execute the schedule job
4. request any api, the response is always slow, and too may close_wait
[image: image.png]

3. Problem Shooting
a) I check the thread with jstack, ClientPoller in NioEndpoint, BlockPoller
in NioBlockingSelector are both in

"http-nio-8043-ClientPoller-0" #83 daemon prio=5 os_prio=0
tid=0x00007faf58b50000 nid=0x4a82 runnable [0x00007faefc8d7000]
   java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
        at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
        at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
        at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
        - locked <0x00000000e3c8b478> (a sun.nio.ch.Util$3)
        - locked <0x00000000e3c8b468> (a
java.util.Collections$UnmodifiableSet)
        - locked <0x00000000e3c8b330> (a sun.nio.ch.EPollSelectorImpl)
        at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
        at
org.apache.tomcat.util.net.NioEndpoint$Poller.run(NioEndpoint.java:798)
        at java.lang.Thread.run(Thread.java:748)

   Locked ownable synchronizers:
        - None
================================================================================
"NioBlockingSelector.BlockPoller-1" #72 daemon prio=5 os_prio=0
tid=0x00007faf591fa800 nid=0x4a77 runnable [0x00007faefd3e2000]
   java.lang.Thread.State: RUNNABLE
        at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)
        at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269)
        at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:93)
        at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:86)
        - locked <0x00000000e3c8bb78> (a sun.nio.ch.Util$3)
        - locked <0x00000000e3c8bb68> (a
java.util.Collections$UnmodifiableSet)
        - locked <0x00000000e3c8ba40> (a sun.nio.ch.EPollSelectorImpl)
        at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:97)
        at
org.apache.tomcat.util.net.NioBlockingSelector$BlockPoller.run(NioBlockingSelector.java:298)

   Locked ownable synchronizers:
================================================================================

b) arthas check https://github.com/alibaba/arthas
i hook the process to see what are the two poller select(selectorTimeout)
return,

the keyCount = 0, but the read buffer have 191 byte to read, why epollWait
always return keyCount = 0?

the expected behavior is, tomcat can read the data from buffer and the
close the socket successfully

c) test with another method
I change the protocol to "Http11Nio2Protocol", and the close_wait will be
recycled

I set java.nio.channels.spi.SelectorProvider with PollSelectorProvider, the
close_wait will be recycled too

Reply via email to