-
Notifications
You must be signed in to change notification settings - Fork 0
Tomcat๊ณผ TCP Backlog
"๋ถํ ํ
์คํธ ์ค TCP ์ปค๋ฅ์
์ ์ค ๋ฌธ์ ๋ฐ์"์์ ๋ค๋ฃฌ ๋ฐ์ ๊ฐ์ด ๋ถํ ํ
์คํธ ์ค์ TCP ์ปค๋ฅ์
์ ๋ํ ์ด์๊ฐ ์์์ต๋๋ค. ํต์ฌ์ ์ธ ์์ธ์ TCP Backlog Queue(accept queue, ๋๊ธฐ์ด) ํฌ๊ธฐ๋ฅผ ์กฐ์ ํด์ฃผ์ง ์์๋ ๊ฒ์
๋๋ค. ๊ทธ๋ฆฌ๊ณ TCP Backlog Queue ํฌ๊ธฐ๋ฅผ ์กฐ์ ํ๋ ๊ณผ์ ์์ Spring Boot ๋ด์ฅ Tomcat์ max-connections์ accept-count ์ค์ ์ ๋ํ ํผ๋์ด ์์์ต๋๋ค.
๊ทธ๋์ TCP Backlog์ accep-count์ ๊ด๊ณ์ ๋ํด์๋ ๊ฐ๋ตํ๊ฒ ์ดํด๋ณด์์ต๋๋ค. ์ด๋ฒ ํฌ์คํ
์์๋ ๊ทธ ๊ด๊ณ๋ฅผ ์ฝ๋ ๋ ๋ฒจ์์ ๋ ๋ถ์ํด๋ณด๊ณ ์ ํฉ๋๋ค.
๋จผ์ Spring Boot ๋ด์ฅ Tomcat์ด ํธ๋ค๋งํ๋ NIO Connector์ ๋ํด ์ดํด๋ณด๊ฒ ์ต๋๋ค.
Tomcat์ ํด๋ผ์ด์ธํธ์ ์์ฒญ์ ์ฒ๋ฆฌํ๊ธฐ ์ํด ์ฌ๋ฌ ์ข ๋ฅ์ Connector๋ฅผ ์ ๊ณตํฉ๋๋ค. ๊ทธ ์ค ๊ธฐ๋ณธ ์ค์ ์ธ NIO Connector๋ Java์ Non-blocking I/O (NIO) ๊ธฐ๋ฐ์ผ๋ก ๋์ํ๋ฉฐ, ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ก ์ฒ๋ฆฌ๋ฉ๋๋ค.
-
Acceptor Thread
ํด๋ผ์ด์ธํธ์ ์ฐ๊ฒฐ ์์ฒญ์ ์๋ฝํฉ๋๋ค. ์ด ๋ ์ปค๋์ TCP Backlog Queue์ ๋๊ธฐ ์ค์ธ ์ฐ๊ฒฐ์ accept()๋ก ๊ฐ์ ธ์ต๋๋ค. -
Poller Thread
์ฐ๊ฒฐ๋ ์์ผ ์ฑ๋์์ ๋ฐ์ดํฐ๊ฐ ๋ค์ด์ค๋์ง(ํน์ I/O ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋์ง) ๊ฐ์ํฉ๋๋ค. NIO์ Selector๋ฅผ ์ฌ์ฉํด non-blocking ๋ฐฉ์์ผ๋ก ๊ฐ์ํฉ๋๋ค. -
Worker Thread
์ค์ ๋ก ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ ์๋ต์ ์์ฑํ๋ ์ญํ ์ ํฉ๋๋ค. ์ฐ๊ฒฐ๋ ์์ผ ์ฑ๋์์ I/O ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด Poller์ ์ํด ์์ปค ์ฐ๋ ๋๋ก ์ ๋ฌ๋ฉ๋๋ค.
๋ด์ฅ Tomcat์ NIO Connector๋ฅผ org.apache.catalina.connector.Connector์ ์์น์์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ Connector๋ผ๋ ํด๋์ค ์์๋ startInternal()์ด๋ผ๋ ๋ฉ์๋๊ฐ ์์ต๋๋ค. ์ด ๋ฉ์๋๋ Spring ์ ํ๋ฆฌ์ผ์ด์
์ ์คํํ ๋ ํธ์ถ์ด ๋ฉ๋๋ค.
๊ทธ๋ฌ๋ฉด Connector.startInternal()์ด ํธ์ถ๋๋ฉด ์ด๋ค ์ผ์ด ๋ฐ์ํ ๊น์? ์ค์ ๋ก ์๋์ ๊ฐ์ ์์๋ก ๊ฐ๊ฐ์ ๋ฉ์๋๊ฐ ํธ์ถ์ด ๋๋๋ฐ, ์ ํฌ๋ NioEndpoint.start()์ ๋ด๋ถ ๋์์ ํํค์ณ ๋ณด๊ฒ ์ต๋๋ค.
Connector.startInternal()
โโโ ProtocolHandler.start()
โโโ Http11NioProtocol.start()
โโโ NioEndpoint.start()
NioEndpoint.start()์ ๋ค์ ๋ ๊ฐ์ง ๋์์ผ๋ก ๋๋ฉ๋๋ค.
-
bindWithCleanup(): socket binding์ ์คํํฉ๋๋ค. -
startInternal():Poller Thread์Acceptor Thread๋ฅผ ์คํํฉ๋๋ค.
์ฒซ ๋ฒ์งธ๋ก bindWithCleanup()์ ์คํํจ์ผ๋ก์จ ์น ์๋ฒ๋ฅผ TCP listening ์ํ๋ก ๋ง๋๋ ๊ณผ์ ์ด ์งํ๋ฉ๋๋ค. ์ด ๊ณผ์ ์์ ServerSocketChannel.bind()๊ฐ ํธ์ถ์ด ๋๋๋ฐ, ์ธ์ ๊ฐ์ผ๋ก accept-count๊ฐ ๋ค์ด๊ฐ๋๋ค.
๋์
ํ accept-count๋ ๋ด๋ถ์ ์ผ๋ก backlog๋ผ๋ ๋ณ์๋ช
์ผ๋ก ํ์ฉ๋ฉ๋๋ค. ์ด backlog ๊ฐ์ด TCP Backlog์ ์ง์ ์ ์ผ๋ก ์ฐ๊ด๋ ๋ถ๋ถ์
๋๋ค.
ServerSocketChannel.bind()์์ ํ ๋จ๊ณ ๋ ๋ค์ด๊ฐ๋ฉด unixBind()๊ฐ ๋์ค๋๋ฐ, ์ด๊ณณ์์ Java ํ์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์ ๊ณตํ๋ listen() ๋ฉ์๋๋ฅผ ํตํด ์์ผ ์์
์ ์ฒ๋ฆฌํ๊ฒ ๋ฉ๋๋ค. ์ค์ ๋ก๋ JNI(Java Native Interface)๋ฅผ ํตํด C/C++๋ก ๊ตฌํ๋ ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค. ์ฌ๊ธฐ์์ listen() ๋ฉ์๋์ ์ญํ ์ ์์ผ์ ๋ฆฌ์ค๋ ๋ชจ๋๋ก ์ ํํ๋ฉฐ, ์ง์ ๋ backlog๋ก ๋๊ธฐ์ด ํฌ๊ธฐ๋ฅผ ์ค์ ํ๋ ๊ฒ์
๋๋ค.
๊ธฐ๋ณธ์ ์ผ๋ก๋ ๋ชจ๋ ํ๋ก์ธ์ค๊ฐ OS์์ ์ค์ ๋ TCP Backlog Queue ํฌ๊ธฐ์ ์ข
์๋์ง๋ง, ๊ฐ ํ๋ก์ธ์ค๋ง๋ค ์ฌ์ฉํ ์ ์๋ ๋๊ธฐ์ด ํฌ๊ธฐ๋ฅผ ๋
ผ๋ฆฌ์ ์ผ๋ก ์ ํํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ Tomcat ์๋ฒ๋ listen() ๊ณผ์ ์์ ์ง์ ๋ accept-count๋งํผ TCP Backlog Queue, ์ฆ accept queue๋ฅผ ์ฌ์ฉํ๋๋ก ์ค์ ํ๊ฒ ๋ฉ๋๋ค.
๋ค์์ผ๋ก NioEndpoint.start()์ ๋ ๋ฒ์งธ ๋์์ธ startInternal()์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ด ๋ฉ์๋์์๋ ์๋์ ๊ฐ์ 3๊ฐ์ง์ ์ค์ํ ๋์์ด ์คํ๋ฉ๋๋ค.
-
initializeConnectionLatch(): max-connections ๊ฐ์ ์ค์ ํฉ๋๋ค. -
pollerThread.start(): Poller Thread๋ฅผ ์คํํฉ๋๋ค. -
startAcceptorThread(): Acceptor Thread๋ฅผ ์คํํฉ๋๋ค.
initializeConnectionLatch()์ ์ญํ ์ ๋จ์ํฉ๋๋ค. max-connections ์ค์ ๊ฐ์ ์ ์ฉํ๋ ๊ฒ์
๋๋ค. max-connections ๊ฐ์ Tomcat์ด ๋์์ ์ฒ๋ฆฌ ๊ฐ๋ฅํ ์ต๋ ์ปค๋ฅ์
์ ๊ฐ์๋ฅผ ์๋ฏธํฉ๋๋ค. ์ด ๊ฐ์ ์ค์ ํ ๋๋ LimitLatch๋ฅผ ํ์ฉํ๋๋ฐ, ์ ์ ํ์ ์ด๊ฒ์ด ์ด๋ป๊ฒ ํ์ฉ๋๋์ง ์์๋ณด๊ฒ ์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋๋จธ์ง pollerThread.start()์ startAcceptorThread()๋ ๋ณด์ด๋ ๊ทธ๋๋ก Poller Thread์ Acceptor Thread๋ฅผ ์คํํ๋ ๊ฒ์
๋๋ค. ์ ํฌ๋ ์ฌ๊ธฐ์ Tomcat๊ณผ TCP Backlog์ ๊ด๊ณ๋ฅผ ๋ถ์ํ๊ณ ์์ผ๋ฏ๋ก Acceptor Thread ์์ฒด๊ฐ ์ด๋ค ์ผ์ ์ํํ๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
์์ ์ธ๊ธํ๋ฏ์ด Acceptor๋ ํด๋ผ์ด์ธํธ์ ์ฐ๊ฒฐ ์์ฒญ์ ์๋ฝํ๋ ์ญํ ์ ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ Acceptor๋ Runnable ๊ตฌํ์ฒด์ด๊ธฐ ๋๋ฌธ์ run() ๋ฉ์๋ ์์ ์๋ ๋ด์ฉ์ด ์ ๋ถ์
๋๋ค. ๊ทธ ๋ด์ฉ ์ค์๋ ์๋์ ๊ฐ์ ์ฝ๋๊ฐ ํฌํจ๋ผ ์์ต๋๋ค.
์ ์ฝ๋์์ countUpOrAwaitConnection()๊ณผ serverSocketAccept()๊ฐ ์ค์ํฉ๋๋ค. ์ฒซ ๋ฒ์งธ๋ก countUpOrAwaitConnection()์ ํด๋ผ์ด์ธํธ์ ์ฐ๊ฒฐ ์์ฒญ์ด max-connections ๊ฐ์ ์ด๊ณผํ์ง ์๋์ง ์ฒดํฌํฉ๋๋ค. ๋ด๋ถ์ ์ผ๋ก๋ initializeConnectionLatch()์์ ๋ฑ์ฅํ๋ LimitLatch๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด๋ ๋์์ ํ์ฑํ๋ ์ ์๋ ์์
์ด๋ ์ฐ๊ฒฐ์ ์ต๋ ๊ฐ์๋ฅผ ์ ํํ๋ ๋๊ธฐํ ๋ฉ์ปค๋์ฆ์ ์ ๊ณตํ๋ ๊ฒ์
๋๋ค. ๋ง์น ์ ํด์ง ์๋งํผ๋ง ์ถ์
์ ํ์ฉํ๋ ๋ฌธ์ ๋น์ฅ(Latch)๊ณผ ๊ฐ์ ์ญํ ์ ํ๋ค๊ณ ์ดํดํ์๋ฉด ๋ฉ๋๋ค.
๊ทธ๋์ LimitLatch.countUpOrAwait()๋ฅผ ํธ์ถํ๊ณ , ๋ง์ฝ ํ์ฌ ์นด์ดํฐ ๊ฐ์ด ์ค์ ๋ ํ๊ณ๊ฐ(์ฌ๊ธฐ์๋ max-connections)๋ณด๋ค ์์ผ๋ฉด ์นด์ดํฐ๋ฅผ 1 ์ฆ๊ฐ์ํค๊ณ , ์ด๋ฏธ ํ๊ณ๊ฐ์ ๋๋ฌํ๋ค๋ฉด ํด๋น ์ค๋ ๋๋ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์์
์ ์๋ฃํ๊ณ ์นด์ดํฐ๋ฅผ ๊ฐ์์ํฌ ๋๊น์ง ๋๊ธฐ ์ํ์ ๋ค์ด๊ฐ๋๋ค. ์ฆ, Acceptor ์ฐ๋ ๋๊ฐ ๋๊ธฐ ์ํ์ ์๋ ๊ฒ์
๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ ๋ฒ์งธ๋ serverSocketAccept()์ธ๋ฐ, Acceptor ์ฐ๋ ๋์ ์ฃผ์ ์์
์ด๋ผ๊ณ ๋ณผ ์ ์์ต๋๋ค. ์ด ๋ฉ์๋๋ฅผ ๋ ๊น์ด ๋ค์ด๊ฐ ๋ณด๋ฉด ์๋์ ๊ฐ์ด ServerSocketChannel.accept()๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. ์ด ์์์๋ ์ค์ ์์ผ ์ฒ๋ฆฌ ์์
์ ์คํํ๋ ๋ฉ์๋(implAccept)๊ฐ ํธ์ถ๋๊ณ , ์ด ์ญ์ JNI๋ฅผ ํตํด C/C++๋ก ๊ตฌํ๋ ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค. ์ฆ, accept queue์์ ๋๊ธฐํ๊ณ ์๋ TCP ์ปค๋ฅ์
์ ๊ฐ์ ธ์ค๋ ์์
์ ์งํํ๋ ๊ฒ์
๋๋ค.
๋ง์ฝ accept queue์ ๋๊ธฐ ์ค์ธ ์ปค๋ฅ์
์ด ๊ฐ๋ ์ฐจ ์๋ค๋ฉด ์๋ก์ด ํด๋ผ์ด์ธํธ์ ACK ์์ฒญ์ด accept-quque์ ์์ด์ง ๋ชปํ๊ณ ์ปค๋ ๋ ๋ฒจ์์ ๋๋กญ๋ ์ ์์ต๋๋ค (SYN ์์ฒญ๋ ๋๋กญ. TCP Backlog Queue ์ฌ์ด์ฆ์ ๋์ผํ๊ฒ ์ํฅ์ ๋ฐ์)
๊ทธ๋์ Acceptor๊ฐ accept()๋ฅผ ๋นจ๋ฆฌ ํธ์ถํด์ ์ปค๋ฅ์
์ accept-queue์์ ๋นจ๋ฆฌ ๊บผ๋ด์ผ ํ๊ฒ ์ง๋ง, ์ด๋ฏธ max-connections๋งํผ์ ์ปค๋ฅ์
์ ์ ์งํ๊ณ ์๋ค๋ฉด Accpetor๋ countUpOrAwaitConnection()์ ๋ด๋ถ ๋ก์ง์ ๋ฐ๋ผ accept()๋ฅผ ํธ์ถํ์ง ๋ชปํ๊ณ ๋๊ธฐ ์ํ์ ์์ ๊ฒ์
๋๋ค. ๋ฐ๋ผ์ accept-count๋ฅผ ๋ฌด์์ ๋๋ฆฌ๋ ๊ฒ์ ์ฐ๊ฒฐ ์์ฒด๋ฅผ ๋ง์ด ์์ ํ ์๋ ์์ง๋ง, Worker ์ฐ๋ ๋๊ฐ ๋ฐ์ ์ํ๋ผ๋ฉด ์์
์ฒ๋ฆฌ๋์ ๋๋ฆฌ์ง๋ ๋ชปํ ๊ฒ์
๋๋ค.
์ง๊ธ๊น์ง Tomcat์ NIO Connector๊ฐ ์ด๋ป๊ฒ ๋์ํ๋์ง, ๊ทธ๋ฆฌ๊ณ TCP Backlog์ accept-count, max-connections ์ค์ ๊ฐ์ด ๊ฐ๊ฐ ์ด๋ค ์๋ฏธ๋ฅผ ๊ฐ์ง๋ฉฐ ์ค์ ์ฝ๋ ํ๋ฆ์์ ์ด๋ป๊ฒ ์ฌ์ฉ๋๋์ง๋ฅผ ์ดํด๋ณด์์ต๋๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก,
-
accept-count๋ OS์ TCP Backlog Queue ํฌ๊ธฐ๋ฅผ ๋ ผ๋ฆฌ์ ์ผ๋ก ์ ํํ๋ฉฐ, -
max-connections๋ ๋์์ ์ฒ๋ฆฌ ๊ฐ๋ฅํ ์ฐ๊ฒฐ ์๋ฅผ ์ ํํ๋ ์ญํ ์ ํฉ๋๋ค. - ๊ทธ๋ฆฌ๊ณ ์ด ๋ ์ค์ ๊ฐ์ Tomcat์ Acceptor ์ฐ๋ ๋์์ ์ปค๋ฅ์ ์ ์๋ฝํ๋ ๋ฐ ์ง์ ์ ์ธ ์ํฅ์ ์ค๋๋ค.
์๋ฒ๊ฐ ๊ณ ๋ถํ ์ํฉ์์ ์ฐ๊ฒฐ ์ ์ค ์์ด ์์ ์ ์ผ๋ก ์๋ํ๊ธฐ ์ํด์๋ ๋จ์ํ ํธ๋ํฝ๋ง ๊ณ ๋ คํ๋ ๊ฒ์ด ์๋๋ผ, ์ปค๋ฅ์ ์ฒ๋ฆฌ ํ๋ฆ๊ณผ ํ์ ์๋ ๋ฐฉ์์ ์ถฉ๋ถํ ์ดํดํ๊ณ , ์ด๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ ์ ํ ํ๋์ ์ํํด์ผ ํฉ๋๋ค.
์ด ๊ธ์ด Tomcat์ ์ปค๋ฅ์ ์ฒ๋ฆฌ ํ๋ฆ์ ์ดํดํ๋ ๋ฐ ์กฐ๊ธ์ด๋๋ง ๋์์ด ๋์๊ธฐ๋ฅผ ๋ฐ๋๋๋ค.