[Full-Stack Network] 5. ZeroMQ

Cherish·2023년 10월 15일
1
post-thumbnail

🍏 프로토콜의 위치

✅ Kernel vs Application

  • 과거
    L1 = HW / L2,3,4 = TCP, IP = OS의 내부 kernel에 위치
  • 현대 : Application layer에 존재
  • OS kernel 안에 있는 경우
    장점 : 성능이 좋다
    단점 : 수정할때 난이도가 높고, OS 회사의 승인이 필요하다 / 새로운 통신 프로토콜을 넣는 것이 어렵다
  • Application Layer에 있는 경우
    장점 : 많은 사람들이 함께 개발할 수 있고, 오픈소스화할 수 있다
    단점 : 성능 저하
    -> Application이 추세. ZeroMQ 포함

✅ 전통적 인터넷 프로토콜 (TCP/UDP/IP)

  • OS안에 존재
  • 성능은 좋지만 허용된 일부의 개발자들만 수정 가능
  • Socket API = 내가 만든 응용프로그램이 kernel안에있는 TCP, IP와 통신하도록 할 때 사용
  • Socket : Application과 Kernel을 이어주는 구멍
  • Unix 계열은 하드웨어 소프트웨어 자원이 file이다. file에 읽고 쓰는 것과 동일하게 동작하기 때문에 운영체제의 file 함수들을 비슷하게 불러서 사용

✅ ZMQ 프로토콜의 위치

in Application Layer

  • ZeroMQ는 운영체제 내부가 아닌, application 레이어 위에 있다.
  • 일부는 TCP를 쓰기도 한다.



🍏 ZeroMQ

= ØMQ, 0MQ, or zmq

  • open-source messaging library
  • 다양한 형태, 서비스에 대해 message를 주고받을 수 있는 라이브러리
  • OS kernel이 아닌 application layer에 있다.
  • 앞선 기능들을 더욱 쉽게 구현하는 것

  • Universal
    지원하는 language, OS가 다양하다.
  • Smart
    pub-sub, push-pull, client server
  • High-Speed
    비동기식으로 미리 만들어져있다 / full-duplex 가능
  • Multi-Transport
    사람들이 사용하는 Transport 계층 위에서 다 돌아갈 수 있다 (TCP/UDP/...)
  • Community
  • The Guide

✅ ZMQ 특징

  • Zero
    broker(반드시 사용해야하는 서버)가 없다.
    zero latency(빠르다), zero cost( free ), zero administration
  • 기본적으로 비동기
  • Berkeley socket API를 일부 가져와서 사용
  • 다양한 messaging pattern 제공

✅ ZMQ Patterns

  • Request-reply
    전형적인 client-server 구조
    1:1, N:M, N:N 모두 가능
  • Pub-sub
    data를 한놈이 만들어서 뿌리는 것 / 공지하는 방식
  • Pipeline
    일을 처리할 떄 여러 일꾼들이 순차적으로 작업을 받고 전달. 결국 fan-out : 뿌려지는 것 / fan-int : 다시 모이는 것 -> PULL, PUSH 사용

✅ ZMQ Sockets

  • Conventional sockets
    직접 다 짜주기
  • ZeroMQ sockets
    ZMQ가 하나의 layer처럼 동작. 기존 처럼 message queue를 관리하며 many-to-many까지 가능하다

✅ Asynchronouse ZeroMQ sockets

  • ZMQ는 기본이 비동기식
  • connection이 있는지와 상관없이 application을 짤 수 있다.
  • Socket의 경우 일정 단위로 해야할 일에 순서가 있었는데, ZMQ는 L1,L2가 끊어지거나 연결이 되지 않아도 데이터를 송수신하게 한다.
    ex) 이동 통신에서 이동해서 연결이 끊기면 Socket programming -> 끊김 / ZeroMQ -> 다시 붙음

✅ ZMQ socket lifetime

  • 소켓에도 옵션을 줄 수 있다.
  • server가 data를 만들어서 보낼 때 다 받을지 일부만 받을 지 filter를 걸 수 있다.
  • 소켓에서의 옵션은 TCP/UDP인지 통신에 대해 주고받는 것에 대한 것에 옵션을 걸었다면 ZMQ는 통신 서비스에 대한 것까지 갈 수 있다.

✅ ZMQ socket bind & connect

일반적으로

  • bind()는 서버에서 호출
  • connect()는 client에서 호출

TCP/UDP에서 원형 버퍼가 있었다. Layer간에도 sending queue/receiving queue가 있다.

  • ZMQ도 마찬가지로 connection 별로 queue를 가진다
    ex) sever가 3개의 clinet와 통신하면 3개
  • ZMQ는 분산처리를 하며 반드시 server가 존재할 필요는 없다. 모든 sw들이 동등하고 하나의 sw가 다른 컴퓨터에게 server로 비춰질 수 있으면서 본인은 client 역할을 할 수 있음.
    -> 따라서 꼭 서버가 bind()를하는 것은 아님.
    본인이 짜는게 client-server가 아니라면 누가 bind/connect 해야하지..?
  • bind( ) : 처음부터 끝까지 유지되는 것 / most stable, 시간적으로 오래 있는 애들
  • connect( ) : 임시로 나타나고 시간이 지나면 없어지고 / 동적으로 되어있는 애들, device들

✅ RabbitMQ

  • 중앙 집중형 MQ
  • 기능이 한정적이기 때문에 우리의 요구와는 맞지 X

ex) 재난 문자 / 스팸 메일
특정 서버를 이용해서 문자를 보내면 SK/KT의 서버 쪽으로 전달. 요청들을 차곡차곡 쌓아두고 하나씩 꺼내서 적절한 지역에 맞춰서 방송. 전달되는 모든 것들은 반드시 broker를 통과한다.

zmq는 기본적으로 소켓 프로그래밍이 1:1 통신밖에 지원 안한거에 비해 다양한것을 제공. 1:1 통신을 이용해 다양한 서비스들을 만듦. 재사용 가능한 일종의 서비스 개발 플랫폼을 만들었다. socket은 라이브러리로 치면 zmq는 좀더 상위개념.



🍏 ZMQ 패턴 및 샘플 코드 이해


✅ Request-Reply pattern

  • client역할을 하는 sw / server 역할을 하는 sw
    - client : request를 보내고
    - server : reply를 보낸다.
    socket과 비슷하다.

✅ REQ-REP : [Synchronous REQ-REP]

  • zmq가 제공하는 패턴 중 하나

[server]

  • import zmq
  • socket을 바로 부르지 않고 zmq.Context()를 통해서 context 객체를 먼저 생성해야 한다.
  • zmq.REP : REP 패턴을 사용하겠다~
  • "tcp를 쓰겠다. 포트번호는 5555다"
  • 무한루프 -> receive 함수를 호출하면 정보를 읽을 수 있어욤. 받으면 화면에 출력을 하고, 1초를 쉬고, 다시 돌려주는 방식

[client]

  • zmq.REQ
  • connect를 통해 bind하고 있는 server에 접속
  • while문 -> 10번동안 hello 보내고 응답('world')받아서 화면에 출력하고~

✅ REQ-REP : [Autonomous 1:N REQ-REP]

  • 수천수만개의 client가 만들어지더라도 아무것도 하지 않는다.
  • 앞선 프로그램을 그냥 실행하면 된다.
  • 서버를 먼저 실행시켜서 bind 상태로 만든 후 client를 하나하나 실행시킨다.


✅ PUB-SUB Pattern

= Publish-Subscribe pattern

  • 이제 socket과 달라짐

  • 정보를 가지고 있고 배포하는 누군가가(Publisher) 있고, 그 정보를 수신하는 자(Subscriber)가 있다.

  • ex) 알람, 재난문자, 주식정보, 날씨 정보 등등

  • 상대방이 구독을 한다면 업데이트할 때마다 무차별적으로 배포를 하는

  • TCP건 UDP건 server는 먼저 떠있어야 한다고 했다. server : bind 하는 주체야! 라고 했다. 근데 지금 부터는 개념이 좀 달라짐. 기능적으로 봣을때 접근을 당하는 애들이 bind 하게 되고 기다리게 된다. server라고 bind 하는 것이 X. 지금의 경우 정보를 제공하는 자가 bind를 하는 것이 맞음. subscriber들은 publisher에 connect하는 형식으로 동작

  • publisher가 subscriber들로부터 connect를 받고 publisher가 정보를 push하면 n개의 subscriber들이 받는다.

example) weather braodcasting

  • 날씨 정보를 가지고 있는 컴퓨터가 있고 접속하는 사용자들이 있다.
  • 누가 connect 하던 동일하게 전송 예정
  • client는 필요한 정보만 볼 수 있도록 세팅할 수 있다. 따라서 client는 setsockopt를 통해 socket을 열면서 option을 줄 수 있다. 서버의 수많은 정보 중에 필요한 정보만 가져와서 쓸 수 있다.

[server]

  • zmq.context()만들고 socket 열기

  • 이번에는 zmq.PUB 패턴

  • publish하는 애를 먼저 띄워야 하니 bind() / 5556번 포트 이용

  • 우편번호 / 온도 / 습도 들을 send_string을 통해 subscribers에게 문자열 send.

  • server 코드에 client의 동작에 대한 코드는 X 개꿀 zmq 안에 알아서 동작이 들어가있음.

[client]

  • import sys : 우편번호를 직접 받기 위해서(입력 파라메터)
  • zeq.SUB
  • server인 5556에 connect
  • 접속해서 모든 정보를 보는 게 아니라 우편번호에 - setsockopt_string을 통해서 zip_filter를 줬어요. zmq는 subscribe 패턴을 써요~를 다시 정의. filter에 대한 정보만 가져올 수 있게 된다.
  • for문 20번 반복 - filter를 통화한 것만 recv_string 가능.
  • split을 통해서 온도/습도 등 나눠서 저장~ 평균도 구해주넹. 이건 zmq랑은 관계 X. 그냥 이 프로그램의 기능


✅ PUB-SUB Socket Characteristics

  • 기본적으로 비동기식
    보내고 싶을때 받고싶을때 받음
  • undirectional
    일방적으로 받거나 일방적으로 보냄. 뒤쪽에서는 섞어서 쓰기도 함.

✅ Publish-Sebscribe with Pipeline pattern

Pipeline Pattern

= PUSH-PULL pattern
병렬적으로 일을 분산해서 처리한 후 결과를 하나로 모으자! = pipeline

  • fan-out : 하나에서 여러개로 퍼지는것
  • fan-in : 여러개가 하나로 모이는 것

여기서 push하는 정보들은 대부분 달라용. R1 / R4 / 등등.. PULL은 이 전부를 받아서 queue(buffer)에 촵촵 저장. 코드에 손을 대면 누구로부터 먼저 받을지도 조정이 가능.


PUSH/PULL example

  • Server는 publish도 하고 pull도 한다.
    pull : 어디서 정보를 가져온다
    publish : 내 정보를 n개에 보낸다
    -> 서버는 pull이 될 수도 pub , req 등ㄷ..등 여러개의 pattern을 가질수 있다!

  • client들은 server가 publish한 정보들을 받을 수 있다(sub). push도 함(client의 상태정보. 어느 개인이 availiable한지 등에 대한 정보들을 push. server에게 ). 그럼 server는 다른 client들에게 정보를 뿌릴 수 있다.

[server]

  • pub/pull 동시에 가능
  • client들이 주기적으로 정보를 보냅니다. 본인이 필요할때 pull 하고, 모든 client에게 pub

[client]

  • sub / push 가능
  • 본인의 상태 정보를 server에 push
  • 다른 client들의 상태는 server를 통해서 받음

Sample Code

[server]

내가 만든 프로그램이 interpreter에게 주어진 최초의 python 소스코드인가에 대한 검사 : if__name main -- 그부분

  • context 열고 PUB / PULL 둘다 있음
  • socket을 두개 열어고, 이름도 다르게 함 publisher / collector(client들의 상태 정보들을 모아서 관리하고있다~ 의미)
  • 얘가 bind 해줌.
  • 반복분 - collector가 client들이 push 한 정보를 pull 해서 다른 publisher들에게 보냄.
  • collector가 receive하고 publisher를 통해서 보내버린다. 정보에 대한 관심 X 암것도 안하고 보내기만

[client]

  • SUB / PUSH 를 위한 socket 열기 & 옵션걸고 & connect
  • b '' : 뒤의 문자가 아스키 코드일 것이다.
  • setsockopt : 옵션 걸기
  • 내가 필요로 할 떄 수신 buffer를 보고 있으면 처리. 바쁘면 나중에 처리
  • poll : 수신 buffer에 데이터가 있어?
  • POLLIN : flag
  • if문으로 수신 buffer에 데이터 있는지 확인하고 그에 따라 처리.

  • 다듬은 버전
    프로그램 이름은 같은데 v2한 거는 client의 아이디를 사용자로부터 받도록 했습니다. main함수를 실행할 때 받음. -> sys.argv에 들어감
    -> client가 id를 가지고 send할 때 id를 줘서 누가 보내는지 알 수 있도록 다듬음.

✅ Dealer-Router pattern

  • 주로 req/rep를 고도화된 기능으로 확대할 때 사용
  • req/rep의 비동기식 버전
  • 1:n과 n:1이 섞여있을 때 사용
  • Server : 라우터같은 기능
    client의 요청을 적절한 worker에게 전달
    client들이 본인이 원하는 기능을 server에게 요청. 그럼 server는 다시 이 일을 여러 명에게 뿌린다. pipeline이랑 헷갈릴 수 있긴 한데, 이 경우에는 클라이언트가 서버에게 요청하면 서버가 워커에게 일을 주고, 워커가 일을 마치면 서버가 받고, 다시 서버가 일을 요청했던 client에게 돌려준다.
  • client는 보내고싶을 때 보내고 받을 때 받는다. 상대는 server 하나에요. server 입장에서는 상대가 여럿이니까 라우터 패턴을 사용.

✅ Asynchronous version of REQ-REP

  • client는 server에게 연결을 하고 응답을 받는다.
  • server는 client의 요청에 대해 응답들을 보낼 수 있다.
  • client는 비동기식이기 때문에 보내고싶을 때 보내고, 기본적으로 여러개의 요청에 앞쪽 응답이 없더라도 보낼 수 있다.
  • server도 여러개의 요청을 받으면 그에 대한 응답을 수시로 보낼 수 있다.


Code - [Server]

  • proxy(router,dealer)
    router - dealer 사이 정보를 그냥 forward한다.
    받아서 다시 socket으로 내보내고, 반복문 만들고, rec, send 호출하고 난리쳐야되는데, zmq에서는 아무것도 안할 때는 proxy를 통해 그냥 둘을 연결해주자!

Code - [Client]

  • 입력 파라메터로 받은 개수 만큼의 worker 생성하고 tcp/udp 방식이 아닌 내부통신 방식으로 연결

[전체 흐름]

  • 클라이언트가 요청한 정보를 server의 router가 받아 proxy로 1:1 연결한 딜러로 전달. 딜러는 누구든 상관없으니 적정한 애에게 전달하고, 에코친걸 받은 dealer는 router 기능을 통해 client에게 전달
  • fair queueing
    아무 것도 하지 않으면 client의 요청을 받은 server는 workder에게 전달할 때 fair하게 전달함. w1 - w2 - w2.

✅ Dealer-Router pattern with Multi-thread Client

  • client도 비동기식 방식으로
  • 수신하는 것 분리

✅ Dirty P2P example

  • P2P를 위해서는 통신을 하고자 하는 컴퓨터는 같은 네트워크에 있어서 network add는 동일하고 host add만 달라야 한다.
  • too heavy



🍏 새로운 Web 기술의 도입

  • 대부분 웹기술은 mozila foundation을 통해 표준화를 하기 때문에 fire fox에 가장 먼저 탑재됨.
  • Java의 장점 : 어느 컴퓨터든 동작 가능 / virtual machine에서 돌아가는 프로그램을 만들기 때문.

Google이 크롬 브라우저를 만들어야할 이유

  • 새로운 기술을 개발하기 원활하게 하도록
  • Web 기술 성능 개선
    웹브라우저는 OS에서 돌아가는 대부분의 어플리케이션을 올릴 수 있다
    -> 그래서 요즘은 OS 안의 TCP IP를 쓰기보다는 본인이 만든다. application layer에서 구현하고 오픈소스화 해서 관심있는 사람들끼리 같이 만들기. 그러면 OS로부터 honorship을 가져올 수 있다.

0개의 댓글