본문 바로가기

Distributed System/이론 공부

분산시스템) 프로세스와 스레드

Processes

이번 포스트에서는 분산 시스템에서 프로세스의 역할이 어떻게 될지, 원격지로 떨어져 있는 컴퓨터 사이에서 프로세스들 간의 관계를 어떻게 지어야 할지에 대한 설계를 고민해본다.

Threads

로컬 컴퓨터에서 concurrent한 task가 동작될 수 있도록 해준다. 다중 스레드의 대표적인 예는 채팅 프로그램이다. 하나는 사용자가 입력하는 input을 기다리는 역할을 하는 스레드가 있고 상대가 보낸 데이터를 화면에 보여주는 역할을 하는 스레드가 필요하다. 따라서 두 개 이상의 스레드가 동시에 돌아가야 한다. 보통 프로그램을 작성할 때 task를 함수 단위로 작성한다. 프로세스와 cost를 비교해보면 스레드를 통해 concurrent 하게 돌리는 것이 context switching overhead가 더 적기 때문에 cost가 더 적게 든다.

Execution of a program

프로세스 하나가 돌려면 반드시 스레드 하나가 필요하다. 스레드나 프로세스는 소프트웨어 리소스이기 때문에 이를 관리하는 주체는 OS이다. 프로그램이 실행된다는 의미가 프로그램이 프로세스가 되는 것이다. 실행 전 파일 상태로 있는 것이 프로그램이고 실행된 것이 프로세스이다. 스레드와 프로세스를 구분할 때 프로세스가 주로 사용하는 OS의 리소스는 메모리이다. 프로세스가 생성되면 프로세스가 구동되는데 필요한 정보는 메모리에 저장된다. 새로 프로세스가 생성될 때마다 남아있는 메모리 중에서 할당을 해준다. 따라서 프로세스 사이에 메모리를 침범하지 않도록 보호해준다. 스레드 간은 공유되는 메모리가 있어서 다중 스레드 프로그래밍을 할 때에는 충돌하지 않도록 주의해야 한다.

Multiple processes

다중 프로세스 상황에서 OS가 concurrency transparency를 제공한다. 사용자가 어떤 프로그램을 실행시키면 다른 프로그램이 실행되고 있는 것을 모르는 채 사용할 수 있다. 프로세스 간에 concurrency를 제공하려면 실행 중인 프로세스를 switching해야 한다. 이 때 실행되는 것을 뺏기는 프로세스에 대한 register values, program counter, stack pointer 등을 저장하고 현재 사용중인 address translation caches를 수정하고 새로 실행할 프로세스의 정보를 로드하는 등 context switch 작업을 해야한다. 스레드에 비해 프로세스는 이런 작업의 cost가 크다. 프로세스가 실행 중일 때 모든 정보를 한 번에 메모리에 올리는 대신 부분적으로 가상화하여 올리는 방식으로 메모리와 하드디스크 상의 swap in, swap out 작업이 이뤄지면서 cost가 더 들 수 있다.

Multi threads

스레드는 프로세스의 하나의 실행 흐름을 관리하는 데이터 구조이다. 프로세스에 비해 관리해야 하는 데이터의 양이 상대적으로 적다. 스레드의 경우 공유하는 메모리가 존재하여 여러 스레드가 동시에 공유 메모리를 접근할 수 있다. OS 상에서 공유 메모리가 충돌이 일어나지 않도록 보호해주지 않고 단지 충돌 상황을 막을 수 있는 메커니즘만 제공한다. 공유된 메모리를 서로 충돌 나지 않도록 잘 짜야한다.

Attractive property of Multi threads

  • blocking system calls
    다중 스레드를 이용하면 전체 프로세스는 block시키지 않으면서 blocking system calls을 쉽게 이용할 수 있다. 한 쓰레드가 block되어있는 동안 다른 쓰레드가 돌면 되기 때문에 다중 쓰레드를 통해 concurrent 한 task를 수행할 수 있다는 의미이다.
  • high performance
    client-server 통신에서 퍼포먼스 향상에 유리하다.

Client 측면에서의 장점

Communication latency

극적으로 통신 지연을 줄일 수는 없지만 전체적인 통신 지연을 다중 스레드를 통해 줄일 수 있다. 웹브라우저와 웹서버가 연결을 맺을 때 텍스트는 보이지만 이미지 콘텐츠는 보이지 않을 때가 있다. 먼저 받은 정보에 대해서 뷰 스레드가 보여주고 이미지를 받는 스레드는 계속 받고 있다. 이런 식으로 하면 사용자가 콘텐츠에 액세스 하는 액세스 딜레이를 줄여줄 수 있다. 그림(a)

Replicated server

서버를 여러 개 두고 데이터를 parallel 하게 받는다. 동일한 데이터에 대해 여러 서버가 부분적으로 보내줘서 그 정보를 모아서 하나의 정보로 만든다. 그림(b)

 

multithread client

server 측면에서의 장점

클라이언트보다 서버 측면에서 다중 스레드의 효과를 더 볼 수 있다.

High performance

서버의 퍼포먼스가 좋다는 것은 가능한 한 빨리 사용자의 요청에 대한 서비스를 제공해주는 것이다. 사용자가 많이 몰리면 서버의 퍼포먼스는 떨어질 수밖에 없다. 그런 와중에도 높은 퍼포먼스를 유지하려면 다중 스레드를 써야 한다. 원격지에 있는 파일을 편집할 수 있는 파일 서버를 예로 들어보자. 서버는 요청이 들어오면 하드디스크에 있는 데이터에 대해 IO를 요청해야 한다.

 

  • Dispatcher thread
    기본적으로 계속 돌면서 client에서 요청이 들어오는지 받는다. 만일 요청이 들어오면 worker thread에게 task를 던져주는 역할을 한다.
  • Worker thread
    요청된 task를 수행한다.

이런 구성으로 요청을 받는 동안 요청된 task를 지속적으로 처리할 수 있다. 만일 서버가 단일 스레드로 구성된다면 main loop 안에서 이런 작업을 계속 반복하게 된다.

 

multithread server

Nonblocking

Blocking system call 대신 nonblocking system call을 이용하면 스레드가 하나임에도 다중 스레드와 같은 효과를 낼 수 있다. 함수를 호출한 후 결과를 기다리지 않고 task가 완료되지 않아도 바로 리턴된다. 다중 스레드의 충돌 문제를 해결할 수 있다.

Asynchronous vs Nonblocking

Asynchronous는 함수 요청을 해놓고 바로 리턴을 받는 것이다. 자신은 리턴을 받았으므로 다른 task를 진행할 수 있지만 이전에 요청한 작업 또한 background로 계속 돌고 있다.

Nonblocking은 바로 읽을 수 있는지 없는지를 확인해보고 읽을 수 있으면 하고 아니면 그냥 바로 리턴 받는 것이다.

작동방식

해당 요청에 대한 state 정보를 계속해서 확인해야 한다.(keep track)

  1. 클라이언트로부터 요청을 받거나 과거 IO 요청했던 것에 대한 완료 메시지를 받는다.(과거 처리 못하고 넘긴 요청도 포함한다.)
  2. 만일 바로 처리가 가능하면 처리하고 끝낸다.
  3. 만일 IO작업이라면 IO 시스템에 asynchronous 하게 요청한다. (대부분 OS에서 IO를 asynchronous하게 쓸 수 있도록 제공해준다.)
  4. 위에 해당 안되면 처리 못한 채로 그냥 리턴한다.
  5. 2, 3, or 4에서 요청받은 작업의 상태 정보를 저장한다.
  6. 현재 하나뿐인 스레드는 2, 3, or 4에서 바로 리턴을 받았으므로 다음 작업을 수행할 수 있다.(1번으로 돌아가서 반복)
Model Characteristics
Threads Parallelism, blocking system calls
Single-threaded process No parallelism, blocking system calls
Finite-state machine Parallelism, nonoblocking system calls