[Network] 백엔드 아키텍처
Listener
네트워크를 통해 들어오는 연결 요청을 대기하고 수신하는 컴포넌트이다.
특정 IP주소와 포트에 바인딩된 소켓을 생성해 그 포트로 들어오는 네트워크 요청을 수신한다.
먼저 운영체제에서 제공하는 네트워크 API를 사용해 네트워크 소켓을 생성하고, 생성된 소켓을 특정 IP와 포트에 바인딩해 해당 소켓이 네트워크 요청을 수신할 수 있도록 한다.
Acceptor
Listener가 감지한 연결을 운영체제의 네트워크 API 중 accept를 사용해 수락한다.
연결이 수락되면 필요한 세션 정보를 초기화하고 클라이언트와의 통신을 준비한다.
Reader
네트워크를 통해 전송된 데이터를 읽고 처리하는 컴포넌트로 데이터를 읽고 애플리케이션에서 사용할 수 있는 형태로 변환한다.
실제 네트워크 요청을 처리하는 컴포넌트로, 엔진엑스에서의 worker와 같은 역할을 수행한다.
프론트엔드에서 Axios 라이브러리를 사용해 GET 요청을 웹 서버에게 보냈다고 하자.
브라우저는 HTTP 요청을 구성하고 TCP Stream을 사용해 서버로 전송한다. (4계층)
서버는 클라이언트로부터 TCP 연결을 통해 전송된 데이터 스트림을 수신하고 Reader가 이 데이터를 읽는다. (7계층)
이 과정에서 HTTP 요청의 URL, 메서드, 헤더, 본문이 분석되고 이에 기반해서 적절한 처리가 진행된다. (7계층)
Single Thread Architecture
백엔드 애플리케이션이 하나의 쓰레드만 사용해 한 시점에 하나의 작업만 처리한다.
uvicorn, Node.js 가 싱글 쓰레드 이벤트 루프 기반 모델을 사용한다.
I/O 작업이 비동기적으로 처리된다. 간단한 구조라 이해하기 쉽다.
Listner Acceptor Reader같은 컴포넌트들은 여러 개 존재할 수 있지만, 이 컴포넌트들은 외부 요청을 수신하고 백엔드 애플리케이션에 전달하는 역할을 수행한다.
백엔드 애플리케이션 자체가 싱글 쓰레드로 작동한다면 요청을 하나씩 처리한다.
Multiple Threads Single Acceptor Architector
멀티쓰레딩을 사용하면 CPU 코어를 제대로 활용할 수 있다.
모든 연결 요청은 하나의 Acceptor 쓰레드에서 처리되고, 수락된 요청의 실제 처리는 여러 작업 쓰레드가 처리한다.
데이터베이스 쿼리 결과, 페이지 렌더링 결과 등을 캐싱할 때 사용하는 Memcached가 이 아키텍처를 사용한다.
CPU 코어 수와 쓰레드의 수를 일치시켜 컨텍스트 스위칭으로 인한 오버헤드를 줄이고 병렬 처리의 이점을 제대로 활용할 수 있다.
모든 요청을 단일 Acceptor 쓰레드가 처리하게 돼 요청이 급증하는 상황에서는 이 쓰레드가 병목 지점이 될 수 있고,
초기 연결 수락 단계에서 로드밸런싱 역할을 처리할 수 없다는 단점이 있다.
자바에서 멀티쓰레딩을 구현할 때는 멀티쓰레드 아키텍처와는 다르게 CPU 코어 수와 쓰레드의 개수를 일치시키지 않아도 되는데, 이는 자바가 컨텍스트 스위칭을 효과적으로 사용해 쓰레드를 처리할 수 있어서이다.
멀티쓰레드 아키텍처에서는 대부분의 쓰레드가 CPU의 계산 능력이 중요한 작업을 수행해 각 쓰레드를 최대한 중단 없이 CPU 코어를 활용할 수 있게 하는 부분이 중요해 CPU 코어 수와 쓰레드의 수를 일치시키는 편이 합리적이다.
CPU의 코어가 4개라면 쓰레드가 4개 할당되고 동시에 4개의 요청만 처리할 수 있는게 이론적으로는 맞다.
하지만 이벤트 루프, 비동기 처리 등으로 몇천, 몇만 건의 요청이 동시에 들어와도 4개의 쓰레드가 동시에 처리하는 것 처럼 보인다.
Multiple Threads Multiple Acceptors Architecture
여러 쓰레드와 여러 Acceptor를 사용해 동시에 여러 네트워크 연결을 관리한다.
하나의 Listener에 여러 Acceptor가 존재해 여러 쓰레드가 동시에 연결을 수락하려 하기 때문에 경쟁 상태와 충돌이 발생할 수 있어 동시성을 관리하는 매커니즘이 필요하다.
이 아키텍처들 외에도 메세지 큐를 사용한다거나, 기존 아키텍처들의 장점을 섞어서 새로운 아키텍처를 만든다거나... 더 나은 구조를 설계하기 위한 여러 방법이 있다.
각 아키텍처가 어느 측면에서 유리하고 어느 측면에서 부족한지 제대로 파악하자.
'Computer Science > Network' 카테고리의 다른 글
[Nginx] nginx.conf (1) | 2023.12.28 |
---|---|
[Nginx] Timeout (0) | 2023.12.24 |
[Nginx] 내부 구조와 리버스 프록시 (1) | 2023.12.21 |
[HTTP] HTTP 쿠키와 세션 (0) | 2023.06.12 |
[HTTP] 헤더 / 쿠키와 캐시 (0) | 2022.08.13 |
댓글
이 글 공유하기
다른 글
-
[Nginx] nginx.conf
[Nginx] nginx.conf
2023.12.28 -
[Nginx] Timeout
[Nginx] Timeout
2023.12.24 -
[Nginx] 내부 구조와 리버스 프록시
[Nginx] 내부 구조와 리버스 프록시
2023.12.21 -
[HTTP] HTTP 쿠키와 세션
[HTTP] HTTP 쿠키와 세션
2023.06.12