본문 바로가기

CS지식/컴퓨터네트워크

Application Layer_ P2P, CDNs, socket programming

분산 시스템이란, 네트워크에 의해 통신해서 어떤 목적의 일을 나눠서 하는 것이다. 일을 나눠서 하는 것을 사람이 알지 못하게 해야한다.

 

P2P 

 P2P(Peer to Peer)는 전통적인 server/client 시스템과는 다르게 역할이 나누어져있지 않고 한 컴퓨터가 서버와 클라이언트 역할을 둘 다 할 수 있는 기술을 말한다. 이러한 기술을 이용하는 각각의 디바이스를 peer라고 한다. 각각의 peer 끼리 직접적으로 통신할 수 있다.  그리고 peer들은 자기가 필요할 때 접속하고 ip주소도 고정되어 있지 않다는 특징이 있다. bittorrent,skype 등이 p2p 서비스에 속한다. 

 P2P에서는 클라이언트가 처음 접속하면 자기가 공유할 데이터가 없기 때문에 서버역할을 못하지만, 데이터를 다운받기 시작하면 그 다음부터 다운받은 데이터를 다른 peer들에게 공유할 수 있다. 

p2p vs client-server 성능비교

  위의 그래프에서 가로축은 클라이언트의 수이다. 클라이언트-서버 모델은 클라이언트 수가 증가할수록 서버가 감당해야 할 작업이 늘어난다. 서버만 일을 하기 때문이다. 그러나 p2p에서는 새로운 클라이언트 즉, peer이 들어오면 동시에 서버로 동작하기 때문에 오버헤드가 천천히 증가한다. 클라이언트 수가 많아지면 p2p 서비스가 유리하다는 것을 알 수 있다.

 

P2P 동작 방식 : BitTorrent

 

 P2P를 이용하여 파일 공유를 할 때에는 파일을 우선 256Kb의 chunk로 나눈다. 이유는 큰 파일 하나를 한번에 한 peer에게 받으려면 받는 동안 계속 연결이 유지되어야 하는데, 유저들은 서버처럼 하루종일 켜져있지 않기 때문에 파일을 일정 크기로 잘라서 각각 다른 peer에게 받는 것이다. 

 torrent란 청크를 주고받는 peer들의 무리를 뜻한다. 

 Tracker는 torrent에 참가하는 peer들을 추적하는 관리시스템이다. 어떤 사용자가 접속하였을 때 사용자가 원하는 데이터를 얻기 위해 어떤 peer와 연결을 수립해야 하는지에 대해 tracker가 제공해준다. 

 

 처음에 사용자가 torrent에 참가하면, 가지고 있는 청크가 없어 서버역할을 하지 못하지만, 조금 있으면 다른 peer들에게 청크를 받아 제공자 역할을 할 수 있게 된다. P2P에서 사용자는 내가 원하는 데이터의 chunk를 나누어 특정 chunk를 누가 가지고 있는지 조사한다. 그리고 가장 적은 수의 peer가 가지고있는 chunk를 우선적으로 받는다. 많은 수의 peer가 가진 chunk는 나중에 요구해도 청크를 받기 수월할 것이기 때문이다. 이러한 정책을 rarest first 정책이라고 한다. 

 

 P2P에서 문제가 되는 것은 자기가 데이터를 받은 만큼 돌려줘야 하는데, 받기만하고 돌려주지 않는 고객이다. 일명 free-rider. 자신의 이익만 취하고 서비스는 하지 않으려는 고객들이다. 이러한 문제를 해결하기 위해 청크를 보낼 때  tit-for-tat이라는 방식을 사용하게 되었다. (잘해주면 잘해주고 못하면 못해주기의 의미) 각각의 peer들은 10초마다 자기한테 가장 데이터를 잘 주는 4명의 peer들을 평가한다. 그리고 그 4명의 peer들 에게 서비스를 잘해준다. 그러면서 매 30초마다 랜덤하게 하나의 peer을 선정해서 청크를 전송해준다. 만약 새로운 연결이 더 우호적이라면 시스템이 원래 peer을 끊고 새로운 연결을 도와준다. 즉, 우호적이지 않은 peer은 배제되는 방식이다. 업로드를 많이 하면 할수록 좋은 peer 파트너를 얻고 빠르게 다운로드 받을 수 있게 된다. 

 

Video Streaming and CDNs

 

 멀티미디어 서비스가 많이 등장하면서 대부분의 인터넷 트래픽은 멀티미디어 트래픽이 차지하고 있다. Netflix와 youtube만 합쳐도 50%이상의 인터넷 트래픽을 장악하고 있다는 것이다. 멀티미디어 서비스를 원활하게 하기 위한 몇가지 방법이 있다. 

 멀티미디어 서비스는 데이터가 크다. 멀티미디어 요청을 한 군데의 서버에서 다 처리하려면 서버에 부하가 매우 커진다.

그리고 멀리 있는 사용자에게 데이터를 전달하는 것도 문제가 생긴다. 그래서 생겨난 것이 CDNs(Content Distribution Networks)이다. 

 큰 멀티미디어 회사들은 서버를 한 군데에 두지 않고 전 세계의 여러 서버를 분산시킨다. 분산된 서버에는 똑같은 컨텐츠들을 저장해놓는다. 만약 사용자가 넷플릭스에 컨텐츠를 요청하면, 넷플릭스 서버는 요구한 고객에 대해 위치나 트래픽 상태를 고려하여 가장 적합한 컨텐츠 서버에 연결해주고, 사용자는 그 서버에서 컨텐츠를 제공받게 된다. 만약 제공해주던 서버의 상태가 안좋으면 다른 서버에 연결해준다. 

 동영상의 압축 크기를 줄여 전송하는 데이터의 크기를 줄이는 방법도 있다. 동영상은 1초당 24장의 사진을 띄워 연속적으로 보이게 한다. 동영상을 이루는 픽셀 하나 당 RGB 값이 들어있다. 한 사진에서 똑같은 값을 가진 픽셀은 위치정보로 구분하여 한번에 압축할 수 있다. 또한, 1초를 이루는24장 중에 똑같은 픽셀을 따로 처리하지 않고, 차이나는 부분만 계산하여 압축하면 동영상을 효과적으로 압축할 수 있게 된다. 동영상 압축 기술은 MPEG를 사용한다. 

 DASH(Dynamic,Adaptive,Streaming over HTTP) 는 고정적인 서비스를 제공해 주는 것이 아니라 트래픽에 따라 상황에 맞는 서비스를 제공하는 것이다. 멀티미디어를 제공할 때, 스트림방식과 다운로더 방식이 있다. 스트림방식은 파일을 받으면서 동시에 보여주는 것이고, 다운로더 방식은 완전히 파일을 다 받을 때 까지 재생이 불가능 한 방식이다. DASH는 스트림 방식을 이용한 서비스이다.

 서버는 하나의 파일을 여러개의 청크로 나눈다. 각각의  청크는 다른 size의 압출률로 여러개의 압축이 존재한다. 각각의 압축은 다른 URL을 가지고 있다. manifesft file에 압축률이 다른 각각의 URL을 모아 관리한다. 

 DASH클라이언트는 연속적으로 가용 네트워크의 대역폭을 측정하고, 이를 기반으로 향후 다운받을 비디오 세그먼트의 비트율을 결정한다.대역폭을 측정하여 전송 속도를 서버에게 알려주면 서버는 그에 맞는 압축 파일을 클라이언트에게 제공하는 것이다.

DASH는 통신량이 안좋으면 화질은 낮지만 용량이 가벼운 URL을 제공해주어 통신 속도를 향상시킨다.

 

클라이언트가 video를 요청하는 예시를 살펴보자

video request

 넷시네마 회사는 웹서버와 DNS 서버만 운영하고 있다. 실질적인 컨텐츠는 다른 서버에게 위탁하고 있다는 것이다. 처음에 밥이 넷시네마 웹서버에서 비디오에 대한 URL을 받는다. 그러면 밥의 local DNS 서버는 넷시네마의 책임DNS서버에 접근해서 자신들의 컨텐츠를 관리하고 있는 CDN의 주소를 받는다. 그 주소를 받으면 밥의 local DNS에서 컨텐츠를 관리하는 DNS서버에 연결해 컨텐츠를 제공받게 된다.

 

Socket Programming

 

 소켓은 사전적으로 구멍,연결,콘센트 등의 의미를 가진다. 주로 전기를 필요로 하는 장치가 전기를 공급받을 수 있도록 전기 공급 인프라 환경에 연결할 수 있게 만들어진 연결부가 소켓이다. 네트워크 프로그래밍에서의 소켓은 어플리케이션 프로세스와 전송계층 사이에 있는 문이라고 할 수 있다. 개발자의 컨트롤에 의해 하위 계층의 네트워크 통신을 조절할 수 있게 된다. 내가 원했던 데이터를 주고받는 것을 의뢰하는 작업이 바로 소켓 프로그래밍이다.

소켓의 실행 흐름

 두 개의 시스템이 소켓을 통해 네트워크 연결을 만들기 위해서는 클라이언트 소켓이 원하는 서버의 소켓에 연결을 요청해야 한다. 그럼 서버 소켓은 연결 요청을 수락하거나 거부할 수 있고, 수락하면 연결이 수립된다. 

 클라이언트 소켓이 처음 소켓을 생성한 다음, 서버 소켓에게 연결을 요청한다. 그리고 서버 소켓에서 연결이 받아들여지면 데이터를 송수신하고, 모든 처리가 완료되면 소켓을 닫는다. (socket() -> connect()->send()/recv()->close())

 서버 소켓의 처리과정은 우선 소켓을 생성하고, 서버가 사용할 ip주소와 포트번호를 생성한 소켓에 결합한다. 그런 다음 클라이언트로부터 연결 요청이 수신되는지 listen하고, 요청이 수신되면 요청을 받아들여 데이터 통신을 위한 소켓을 생성한다. 그런 후에 데이터 송수신을 처리하고 작업이 완료되면 소켓을 닫는다. (socket()->bind()->listen()->accept()->send()/recv()->close())