Libzmq Chapter 2 - Sockets and Patterns

From 탱이의 잡동사니
Jump to navigation Jump to search

챕터 1에서 간단한 ZeroMQ 의 기본 패턴들을 살펴보았다(request-reply, pub-sub, pipeline). 이번 챕터에서는 실제 프로그램에서 이를 어떻게 응용하는지를 살펴보도록 하자.

다음을 살펴볼 예정이다.

  • ZeroMQ 소켓의 생성과 사용
  • 소켓을 이용한 Messsage send/receive
  • ZeroMQ 비동기 I/O 를 이용한 Application 작성
  • 단일 thread 에서 다중 소켓 사용
  • fatal/nonfatal error 관리
  • Interrupt signal(ctrl+c) 관리
  • ZeroMQ 종료 방법
  • ZeroMQ 어플리케이션 메모리 누수 탐지
  • Multipart 메시지 send/receive
  • 네트워크 메시지 forward.
  • 간단한 Message queuing broker 작성법
  • ZeroMQ를 이용한 멀티 쓰레드 프로그램 작성법
  • ZeroMQ 를 이용한 쓰레드 signal 전송
  • ZeroMQ 를 이용한 네트워크 노드 조정
  • pub-sub 에서의 message envelope
  • 메모리 오버플로우를 막기 위한 HWM(high-water mark) 사용법.

The Socket API

정말 솔직하게 이야기하자면, ZeroMQ 는 일종의 switch-and-bait 방식으로 동작한다. ZeroMQ는 메시지 프로세싱과 관련한 내용을 숨기고 Socket-based API 를 제공하기때문에 큰 이점을 준다.

Socket 은 네트워크 프로그래밍에서의 사실상의 표준(De facto standard)이다. ZeroMQ 를 더욱 더 돋보이게 만드는 점은 어떤 특별한 컨셉을 적용하는 것이 아닌 일반적인 소켓을 사용한다는 점이다.

먹기 좋은 음식처럼, ZeroMQ 역시 받아들이기 쉽다. ZeroMQ 의 소켓의 사용은 BSD 소켓과 같이 크게 4가지 부분으로 나뉜다.

  • 소켓을 생성하고 종료한다. Creating and destroying sockets. (zmq_socket(), zmq_close()).
  • 필요할 경우, 소켓의 속성을 확인하고 설정한다. Configuring sockets by setting options on them and checking them if necessary. (zmq_setsockopt(), zmq_getsockopt())
  • 소켓을 네트워크와 연결한다. Plugging sockets into the network topology by creating ZeroMQ connections to and from them. (zmq_bind(), zmq_connect())
  • 소켓을 이용하여 메시지를 송신/수신 한다. Using the sockets to carry data by writing and receiving messages on them. (zmq_msg_send(), zmq_msg_recv())

소켓은 언제나 void pointer 이고, 메시지는 structure 라는 것을 기억하자. 이 때문에 c 에서는 zmq_msg_send() 와 zmq_msg_recv() 와 같이 메시지의 주소를 전달하는 것 만으로 ZeroMQ 를 사용할 수 있다.

소켓의 생성, 종료, 수정은 정확히 사용자가 생각한대로 동작한다. 하지만 ZeroMQ 는 비동기 방식이며 유연하게 동작한다는 것을 기억하자.

Plugging Sockets into the Topology

두 개의 노드사이에 연결을 설정하기 위해서는 한쪽의 노드에서 zmq_bind() 를 사용하고, 다른쪽에서는 zmq_connect() 를 사용해야 한다. 간단하게, zmq_bind() 를 사용하는 쪽이 server 가 되고, zmq_connect() 를 사용하는 쪽이 client 가 된다.

ZeroMQ 를 통한 connection 은 기존의 TCP connection 과는 약간의 다른점이 있다. 크게 다음과 같이 나타낼 수 있다.

  • 여러가지 transport 계층을 사용할 수 있다(inproc, ipc, tcp, pgm, epgm, ...). zmq_inproc(), zmq_ipc(), zmq_tcp(), zmq_pgm(), zmq_epgm() 을 보라.
  • 하나의 소켓이 여러개의 in/out connection 을 가질 수 있다.
  • zmq_accept() 는 없다. 소켓이 connection 을 시도할 때, 자동으로 accept 가 된다.
  • connection 이 끊어질 경우, 자동으로 재접속을 시도한다(네트워크의 연결이 끊어졌다 연결되었을 경우).
  • ZeroMQ 를 사용하는 application 들은 이 connection 에 직접적으로 접근할 수 없다. 캡슐화 되어있다.

많은 수의 아키텍쳐들이 client/server 모델을 따른다. 이 모델에서 보통 server 는 정적이고, client 는 동적으로 작동하게된다. 가끔 addressing 과 관련된 이슈들이 발생하게 되는데, server 는 필연적으로 client 에게 주소(위치)가 노출되는 반면에 client 는 그렇지 않아도 된다. 때문에 명확하게 어느쪽이 zmq_bind() 를 수행해야 하고(server), 어느쪽이 zmq_connect() 를 수행해야(client) 하는지를 알 수 있다. 물론 가끔 특별한 네트워크에서는 조금 다를 수 있다.

이제, server 를 시작하기전에 client 를 시작해보자. 전통적인 네트워킹에서라면 아마 시작과 동시에 에러를 확인할 수 있을 것이다. 하지만 ZeroMQ 는 어느쪽이 먼저 시작하던 상관없도록 해준다. client 에서 zmq_connect()를 함과 동시에, connection 이 생성되고 소켓을 통해 메시지를 전송할 수 있게 된다. 그리고 이후 server 가 실행되면(큐에 메시지가 가득차서 메시지를 discard 하기 전에) ZeroMQ 는 메시지를 전송하기 시작한다.

server는 하나의 소켓을 이용해서 여러개의 endpoint(프로토콜과 address 의 조합) 를 가질 수 있다. 즉, 서로 다른 transport 를 통한 connection 을 받아들일 수 있다는 뜻이다. <source lang=c> zmq_bind(socket, "tcp://*:5555"); zmq_bind(socket, "tcp://*:9999"); zmq_bind(socket, "inproc://somename"); </source>

대부분의 transport 들이 그러하듯, 하나의 endpoint 를 두번 할당할 수 있다.

비록 ZeroMQ 에서 어느쪽이 bind를 하건, connect 를 하건 상관이 없도록 한다지만, 어느정도 차이점은 있다. 이 차이점에 대해서는 나중에 깊게 살펴볼 예정이다. 짧게 말하면, server 란, 좀더 고정적인 endpoint 를 bind 를 하는 쪽이며, client 는 동적인 부분을 담당하며 connect 를 하는 쪽이라고 보면 된다.

소켓에는 타입이 있다. 소켓의 타입은 소켓의 속성을 정의한다. 메시지의 내부/외부 라우팅, Queuing, etc 등을 정의한다. 여러개의 타입들을 연결할 수 잇다(예를 들면 publisher/subscriber). 소켓은 "message pattern" 의 형태로 동작하게 된다. 나중에 깊게 살펴 볼 것이다.

이와 같이 ZeroMQ 에서는 소켓들을 조금 다른 방식으로 connection 하게 되는데, 바로 이 점이 ZeroMQ 로 하여금 Message Queuing System 으로써의 동작하게 하는 것이다. 여기에 proxy 와 같은 계층이 위에 올라가게 된다(나중에 살펴볼 것이다). 하지만 기본적으로 ZeroMQ 를 이용하게되면, 아이들의 블럭 장난감처럼 네트워크 아키텍쳐를 마음껏 가지고 놀 수 있게 된다.

Sending and Receiving Messages

메시지를 송신하고, 수신하기 위해서는 zmq_msg_send() 와 zmq_msg_recv() 를 사용해야 한다. 전통적인 이름이지만, ZeroMQ 의 I/O 모델을 알게된다면, 기존의 TCP 와는 다른 방식으로 작동한다는 것을 알게 될 것이다.

See also