소켓(socket)은 떨어져 있는 두 호스트를 연결해주는 도구로, 데이터를 주고받기 위한 창구 역할을 한다. (TCP/IP Socket) 클라이언트 소켓과 서버 소켓이 소켓 API를 호출 하고, 응답하는 것이 네트워크가 되는 것이다.
그런데 하나의 서버 소켓이 응답해야 하는 클라이언트 소켓이 여러개라면 어떻게 해야 할까?
SELECT 함수는 이것을 가능하게 해준다. (I/O multiplexing) 소켓이 닫힐 때까지 처리할 요청이 있는지 확인하고, 동시다발적으로 요청들을 처리한다. 1 소켓 1 쓰레드의 thread-model 이다.
이것이 Tomcat 의 기본 개념이다. 톰캣은 default thread pool 이 200을 갖고 있어, 기본적으로 200 개의 동시 요청에 대해 응답할 수 있다. 그렇다면 200개 이상의 concurrency request 가 온다면? thread busy 상태가 될 것이다. 그렇다면 thread pool을 500으로 늘리면 되지 않겠는가? 안된다. 쓰레드 수를 무한정 늘리게 되면 CPU는 더 많은 context switching을 해야하고, 메모리 낭비 문제도 발생한다.
여기서 request 와 response는 하나의 쓰레드에서 다룬다. (thread safety 가 보장되어 있다) 이걸 기반으로 한 것이 servlet 이고, 또 다시 이것을 spring framework화 한 것이 바로 Spring MVC 이다.
앞서 말했지만, 쓰레드 수를 무한정 늘릴 수는 없다. 그렇다면, 하나의 쓰레드에서 request, response, business logic을 모두 수행한다는 고정관념을 깨야 한다. 이것이 바로 Reactive Streams 이며, Reactive Streams는 non-blocking, asynchronous 프로그래밍을 위한 programming interface 이다.
Publisher 는 데이터를 흘려준다.
Subscriber는 데이터를 받아간다.
데이터의 양을 정할수 있는 것은 subscriber이다. 기존의 개념에서는, publisher 가 subscriber 에게 pressure를 준다. 하지만, reactive streams 에서는 반대이다. subscriber 가 publisher 에게 back-pressure로 받아갈 데이터를 요청한다.
이 방식을 사용하면, 쓰레드 개수는 2-30개로 충분하다. 중요한 것은 back-pressure 이다. 하나의 쓰레드가 데이터를 보내고, 받는다는 편견을 버려라. 주의해야 할 점은, 더 이상 thread-safety가 보장되지 않는다는 것이다. immutability를 더욱 신경써야 한다.
RX Java / RX Java2 는 Reactive Streams 의 구현자이다.
하지만, RX Java 의 back-pressure 구현에는 문제점이 존재하기 때문에, Reactor 가 만들어졌다.
이 Reactor를 잘 사용해서 비즈니스까지 데려다주기 위해, 우리는 Spring Webflux를 사용한다.