프로그래밍 초식 : 서버에서 비동기 I/O 사용하는 이유

Donghun Seol·2023년 4월 29일
0

프로그래밍 초식

목록 보기
11/13

레퍼런스

요청당 쓰레드 모델 - (thread per request)

서버가 요청별로 개별 쓰레드를 생성하는 모델이다. 웹서버의 특성상 I/O 대기(클라이언트 송수신, DB 송수신) 시간이 전체 처리 시간에서 많은 비중을 차지하므로, CPU가 노는 시간이 많아진다.

스프링과 노드의 차이

  • 자바 스프링은 thread-per-request 모델을 따르고, 노드는 싱글스레드 기반으로 동작한다.
  • 스프링도 리액터나 웹플럭스를 통해 비동기 모델로 동작하게 할 수 있지만 일반적인 상황에서는 추천하기 힘들다.

컨텍스트 스위칭

쓰레드/프로세스 전환 과정에서 현재 작업중인 쓰레드/프로세스의 프로그램 카운터, 스택에 있는 변수 등을 저장하고 로드하는 작업을 수행한다. 당연히 컴퓨팅비용이 소모되어 지나친 컨텍스트 스위칭의 발생은 성능에 부정적 영향을 미친다.

고부하 상황에서 요청당 쓰레드 모델의 단점

  1. I/O 대기로 인한 CPU 낭비 증가
  2. 쓰레드가 많아지므로 컨텍스트 스위칭 비용 증가
  3. 쓰레드별 스택이 필요하므로 메모리 사용 증가

CPU, 메모리 사용이 급증하여 처리량 향상이 제한되고 응답시간이 증가한다. 따라서 접속 가능한 클라이언트 수에 제한이 발생한다.

비동기 I/O를 사용하면 위와 같은 문제 해결가능하다.

I/O가 끝나길 대기하지 않고, 콜백, 이벤트 형태로 결과를 받는다.
I/O 처리에는 사전에 정해진 고정된 개수의 쓰레드를 사용한다.
노드에서 사용하는 방식.

클라이언트의 수에 비례해서 쓰레드가 추가적으로 생성되지 않고, I/O 대기에 따른 CPU 유휴시간이 줄어든다. 따라서 선응이 향상될 수 있다.

비동기 I/O로 얻는 이점 다시 정리

자원의 효율 증가

  • I/O에 따른 쓰레드 대기(=CPU 유휴시간)이 없음
  • 쓰레드 개수 일정하게 유지하여 메모리상 추가적인 스택 할당 필요없음

더 적은 자원으로 많은 클라이언트 처리 가능

간단한 소켓 서버에서 다음과 같은 성능 차이 발생

  • 동기 I/O : 메모리 1.5G 기준 7.5K 동시 연결 처리
  • 비동기 I/O : 메모리 1.5G 기준 120K 동시 연결 처리

항상 그렇듯이 비동기가 "만능"은 아니다.

비동기 처리에 따른 복잡도가 증가한다.

  • 콜백 등의 사용으로 코드가 복잡해진다. async/await 로 개선은 가능하지만..
  • 실행 컨텍스트를 충분히 파악하지 않으면 디버깅이 어렵다.

대량 트래픽이 아니면 동기/비동기 차이가 크진 않다.

  • TPS가 수천 미만이거나 동접이 천명가량되는 채팅 서버 등의 경우

I/O 위주 처리가 아니면 효과가 적다

  • CPU Bound 작업을 비동기를 넣으면 안된다.

동기와 비동기메서드가 섞이면 역효과 발생가능하다. 따라서 개발자는 언제 동기/비동기 메서드를 사용할지 잘 파악하고 있어야 하고 신중히 선택해서 코딩해야 한다.
(그런데 자바에서와는 다르게 노드에서는 거의 대부분 비동기를 메서드를 사용하는 것이 적절하다고 생각한다. V8 엔진의 작동 방식이 지겹게 들어왔던 싱글스레드, 이벤트루프, 이벤트기반, 논블록I/O 방식이기 때문이다.)

profile
I'm going from failure to failure without losing enthusiasm

4개의 댓글

comment-user-thumbnail
2023년 5월 7일

OpenAI API 를 활용해 다음과 같은 답글을 포스팅에 자동으로 달아주는 프로젝트를 구상중입니다.
생각하고 있는 워크플로는 다음과 같습니다.

  1. 깃헙 액션스에서 주기적으로 새로운 아티클을 탐색한다.
  2. 신규 아티클이 존재하면 액션스크립트에서 크롤링한 블로그 컨텐츠를 가지고 AWS lambda에 POST 요청한다.
  3. lamada는 OpenAI API의 Wrapper로 동작한다.
  4. 응답을 댓글봇 계정으로 댓글을 단다.
  5. 일단 내 개인 블로그 대상으로만 테스트하고 구현해본다.
  6. 성공하면 오픈소스 프로젝트로 깃헙 액션스에 올려본다.

프롬프트 :

Please review this backend development blog post by providing a summary, pointing out incorrect content, fixing any inaccuracies with relevant reference links, and suggesting additional topics or resources for further study : <블로그 본문>

결과 :

The blog post discusses the differences between thread-per-request and asynchronous I/O models in backend development. It highlights the advantages and disadvantages of each approach, comparing Java Spring (which follows the thread-per-request model) and Node.js (which operates on a single-threaded, event-driven, non-blocking I/O model). The post also mentions the benefits of asynchronous I/O, performance comparisons, and the complexities introduced by asynchronous programming.

Incorrect content:
There isn't any obviously incorrect content in the blog post. However, it might be useful to expand on some points or provide clearer explanations.

Suggestions for additional topics or resources:

More in-depth comparison between Java Spring and Node.js, discussing factors like performance, scalability, and developer experience.
Explore other backend development frameworks and languages, such as Python's Django or Ruby on Rails, and how they handle I/O operations.
Discuss the role of microservices architecture in backend development and how it affects the choice between synchronous and asynchronous programming.
Provide practical examples of implementing both thread-per-request and asynchronous I/O models in real-world applications.
Explain the concept of event loop in Node.js and how it contributes to its asynchronous I/O handling.
Discuss the C10k problem and how it led to the development of asynchronous I/O models.
Relevant resources:

Java Spring documentation: https://docs.spring.io/spring-framework/docs/current/reference/html/index.html
Node.js documentation: https://nodejs.org/en/docs/
Event loop in Node.js: https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
The C10k problem: http://www.kegel.com/c10k.html
Python Django documentation: https://docs.djangoproject.com/
Ruby on Rails documentation: https://guides.rubyonrails.org/

답글 달기
comment-user-thumbnail
2023년 5월 12일

sample mocking comment for api test

답글 달기
comment-user-thumbnail
2023년 5월 13일

sample mocking comment for api test

답글 달기
comment-user-thumbnail
2023년 5월 13일

sample mocking comment for api test

답글 달기