Sync, Async / Blocking, Non-Blocking
Introduction
보통 입출력에서(네트워크 통신 포함) 많은 시간과 비용이 소요됩니다. 그렇기 때문에 이것을 어떻게 처리할 것에 대해 논의하면서 이 주제가 부각되었습니다.
C10K 문제와도 관련이 있는데요. 하나의 서버에서 1만명의 클라이언트를 처리할 수 있는가입니다. 멀티쓰레드에서 쓰레드 수가 그만큼 있다고 해도 메모리가 너무 많이 차지하고 문맥 교환비용이 많이 발생하기 때문에 힘듭니다.
블록킹과 논블록킹의 구분은 비교적 명확하지만 동기, 비동기의 구분은 명확하진 않은 편입니다.
- 호출하는 함수가 제어권을 가지고 있는지 유무 → blocking, non-blocking
- 호출되는 함수의 완료여부를 신경 쓰느냐 → synchronous, asynchronous
System Call
프로세스가 하드웨어에 접근해서 직접 필요한 기능을 사용하는 것을 말합니다. 내부는 사용자 모드, 커널 모드로 구성되어 있습니다. 사용자 모드에서 특권 명령을 실행하여 trap을 실행해 커널 모드에 접근합니다.
특징
- Sync : System call 완료를 기다립니다.
- Async : System call 완료를 기다리지 않습니다.
- Blocking : os 대기큐에서 기다립니다.
- Non-Blocking : os 대기큐에서 기다리지 않습니다.
동기 여부와 블로킹 여부의 조합을 통해 4가지 형태로 사용될 수 있습니다. 하지만 실제로 다 가능한 상황은 아닙니다.
파일 IO 요청, 네트워크 IO 요청 2개가 동시에 발생했다고 가정해봅시다.
Blocking / Sync
- 최악의 상황으로 속도가 가장 느립니다.
Non-Blocking / Async
- 하나의 스레드를 가지고 2개의 요청을 처리합니다.
- 완료 여부를 물어보지 않고 각각의 요청이 처리되고 있다가 완료가 되면 User App 에게 바로 응답을 보냅니다.
- 가장 성능이 좋습니다.
Non-Blocking / Sync
- 하나의 스레드를 가지고 2개의 요청을 처리합니다.
- 운영체제는 그 스레드에게 완료여부를 물어봅니다. 그리고 각각의 요청이 처리되고 있다가 완료여부를 물어 완료되었을 때 User App에게 응답을 보냅니다.
Blocking / Aync : 실제로 가능하지 않은 상황입니다.
Node js 동작방식
그럼에도 불구하고 대량의 서비스의 경우 Spring을 많이 사용하는 이유는 다음과 같습니다
- call back hell
- call back 구현하는 것이 힘듭니다.
- 서버가 다운되기 쉽습니다. 불안정하기 때문입니다.
app에서의 Async, sync
만약 회원가입하고 회원가입시 요청 완료 메일을 보낸다고 가정해봅시다. 회원을 DB에 등록하는 작업과 메일 보내는 작업, 총 2개의 요청이 발생합니다. 이 경우 메일의 경우 당장 필요한 요청이 아니기 때문에 Spring의 @Async
어노테이션을 사용하여 비록 메일 요청이 완료되지 않더라도 다른 작업을 계속할 수 있습니다. 따라서 응답 속도를 빠르게 할 수 있습니다. 이런 상황의 경우 위 어노테이션을 사용할 수 있습니다.
이해를 제대로 했다면 다음 질문을 말할 수 있어야합니다.
어떻게 싱글 쓰레드인데 다수의 요청을 처리할 수 있습니까?
'CS' 카테고리의 다른 글
웹을 지탱하는 기술3 - HTTP (0) | 2019.03.07 |
---|---|
프로세스와 쓰레드 (0) | 2019.02.25 |
프로세서와 코어의 차이점 (2) | 2019.02.08 |
TCP/IP (0) | 2019.01.30 |