Spring reactor.
3 min readDec 22, 2020
non blocking base web framework. 삽질기
- block()/blockFirst()/…..
cpu 코어 갯수 만큼 기본 event를 받는 thread가 생기고, i/o 쓰레드 들이 생기고… 미리 정의된 pool들이 생긴다.
하지만 그중 nonBlocking thread에서 block을 하게 되면, 성능에 큰 문제를 야기 할 수 있다. 그 이유는 event loop 를 기반으로 만들어 졌기 때문에, 자칫하면 이벤트 루프를 블럭 시키게 되고, 다른 사용자의 요청 자체를 받지 않게 되는 상태를 야기 할 수 있다. 때문에 위 에러가 발생하면서 블럭킹을 할 수 없다고 나오는 에러는, 그러한 상황을 막기 위한 방어책 이라고 보면된다. 현재 context thread가 어떤 종류 인가에 따라 허용되기도, 비허용 되기도 한다.
동일 주제로 검색을 해보면 대다수의 답변들은, 블로킹을 하려는 이유가 무엇인가? 하지 않고도 충분히 니가 원하는 로직을 구현 할 수 있다.
구현 로직을 재검토하길 바란다는 내용들로 넘쳐난다.
나에게 혼란을 줬던 부분이 이것인다. 모든 것들을 논블로킹으로 작성해야만 하는가? 라는 질문에 가능할 거라고 생각지 못한 케이스 들이 분명 있을 것이고, 그러한 경우엔 어떻게 블로킹을 할 수 있을 까를 찾던 나에겐… 별로 도움이 되는 답변들이 아니였다.
하지만 위 답변들이 가장 옳다. 논블로킹으로 대다수 해결이 가능하다.
다만 블로킹이 정말정말 필요하면 별도의 scope에서 실행되도록, subscribeOn(Schedulers.elastic) 과 같이 동작할 쓰레드풀을 지정해주면 된다. (그래도 분명 방법은 있으니.. 블로킹은 되도록 하지 말자) - 어떻게 써야하는가?
사실 나도 이 질문에 완벽한 답을 할 경험은 없다.
단지 하루 이틀 정도 머리아프게 만져보고 나니까.
메서드를 설계할때 부터 고민이 많이 필요하다는 것을 느꼈다.
리턴타입이 Mono, Flux 라면 분명 논 블로킹하게 사용하라는 힌트가 될 수 도 있다. 원작자의 의도를 일관되게 보여야 하고, 별도의 풀에서 동작해야 하는 경우와 아닌 경우를 명확하게 구분되도록 하는게 좋고, 동시에 동작해야 하는 경우라면 Zip과 같은 연산을 적극 활용 한다던지, 레퍼런스나 도큐먼트를 정독하고 적절하게 사용하도록 노력이 필요하다.
그렇지 않으면 오히려 성능적으로 더 구린 시스템을 만들 가능성이 아주 크다. - 결론
공부가 필요하고, 러닝커브가 있다. 절차적인 방법이더 나은 경우도 있다.
하나의 도구이고 방법이지 만능은 아니기 때문에 기술 선택에 있어서 유행을 따라 선택하려는 의도라면 제대로 이해하기 전까지는 그다지 추천하고 싶지는 않다.
리엑터를 제대로 공부하지 않고 작성한 코드들 때문에..(타인)
해당 시스템은 1년도 되지 않아 가독성 최악, 로직 파악이 어려운 레거시가 되어버렸다….