Docker에서 standalone Pulsar 클러스터 실행하기

Docker에서 standalone Pulsar 클러스터 실행하기

로컬 개발과 테스트를 위해 Docker 컨테이너 안에서 자신의 머신에 standalone 모드로 Pulsar를 실행할 수 있어요. Docker를 쓰면 환경 구성 걱정 없이 바로 Pulsar를 띄워볼 수 있죠.

컨테이너를 시작하고, Pulsar 클라이언트로 메시지를 주고받고, REST API로 토픽 통계를 확인하는 흐름까지 이어서 살펴볼게요.

출처: 문서

본문

사전 준비 (Prerequisites)

  • Docker (20.10+ 권장)
  • 사용 가능한 RAM 최소 4GB
  • 여유 디스크 공간 최소 5GB

1단계: Docker에서 Pulsar 시작 (Start Pulsar in Docker)

macOS, Linux, Windows에서 다음 명령으로 Docker 컨테이너 안에서 Pulsar를 시작해요.

macOS & Linux:

docker run -it \
-p 6650:6650 \
-p 8080:8080 \
--mount source=pulsardata,target=/pulsar/data \
--mount source=pulsarconf,target=/pulsar/conf \
apachepulsar/pulsar:5.0.0-M2 \
bin/pulsar standalone --advertised-address localhost

Windows:

docker run -it ^
-p 6650:6650 ^
-p 8080:8080 ^
--mount source=pulsardata,target=/pulsar/data ^
--mount source=pulsarconf,target=/pulsar/conf ^
apachepulsar/pulsar:5.0.0-M2 ^
bin/pulsar standalone --advertised-address localhost

팁: 이 예시들은 기존 로컬 Docker 동작을 유지하기 위해 --advertised-address localhost를 설정해요. 클라이언트는 호스트 머신의 localhost:6650에 연결할 수 있고, 브로커도 이후 연결에 사용할 주소로 localhost를 클라이언트에 광고해요.

이 옵션을 생략하면 Pulsar는 기본적으로 컨테이너의 FQDN을 사용해요. 이는 광고된 호스트 이름이 클라이언트에서 해석 가능하고 도달 가능할 때(같은 네트워크의 다른 컨테이너나 원격 호스트 등) 잘 동작하지만, 컨테이너 밖에서 그 FQDN에 도달할 수 없다면 호스트 머신의 클라이언트가 깨질 수 있어요.

기본적으로 Pulsar는 메타데이터 저장소로 RocksDB를 사용해요. standalone 인스턴스에 권장되는 옵션이에요.

RocksDB에 문제가 있거나 기존 ZooKeeper 기반 설치와의 호환이 필요하다면, 다음을 추가해 메타데이터 저장소로 ZooKeeper를 사용할 수 있어요.

...
-e PULSAR_STANDALONE_USE_ZOOKEEPER=1 \
...

참고: 메타데이터 저장소를 바꾸면 새 클러스터가 만들어져요. 처음부터 다시 시작하려는 게 아니라면 기존 인스턴스에는 적용하지 마세요.

Pulsar 구성을 변경하고 Pulsar를 시작하려면, PULSAR_PREFIX_ 접두사가 붙은 환경 변수를 전달하는 다음 명령을 실행해요. 자세한 내용은 기본 구성 파일을 참고해요.

macOS & Linux:

docker run -it \
-e PULSAR_PREFIX_xxx=yyy \
-p 6650:6650  \
-p 8080:8080 \
--mount source=pulsardata,target=/pulsar/data \
--mount source=pulsarconf,target=/pulsar/conf \
apachepulsar/pulsar:5.0.0-M2 sh \
-c "bin/apply-config-from-env.py \
conf/standalone.conf && \
bin/pulsar standalone --advertised-address localhost"

Windows:

docker run -it ^
-e PULSAR_PREFIX_xxx=yyy ^
-p 6650:6650  ^
-p 8080:8080 ^
--mount source=pulsardata,target=/pulsar/data ^
--mount source=pulsarconf,target=/pulsar/conf ^
apachepulsar/pulsar:5.0.0-M2 sh ^
-c "bin/apply-config-from-env.py ^
conf/standalone.conf && ^
bin/pulsar standalone --advertised-address localhost"

팁:

  • Docker 컨테이너는 기본적으로 UID 10000과 GID 0으로 실행돼요. 마운트된 볼륨이 UID 10000 또는 GID 0에 쓰기 권한을 주는지 확인해야 해요. UID 10000은 임의의 값이므로, 루트 그룹(GID 0)에 이 마운트들을 쓰기 가능하게 만드는 것을 권장해요.
  • 데이터, 메타데이터, 구성은 Docker 볼륨에 지속되어 컨테이너가 다시 시작될 때마다 "처음부터" 시작되지 않아요. 볼륨에 대한 자세한 내용은 docker volume inspect <sourcename>을 사용할 수 있어요.
  • Windows용 Docker에서는 Linux 컨테이너를 사용하도록 구성했는지 확인해요.

Pulsar가 성공적으로 시작되면 다음과 같은 INFO 레벨 로그 메시지를 볼 수 있어요.

08:18:30.970 [main] INFO  org.apache.pulsar.broker.web.WebService - HTTP Service started at http://0.0.0.0:8080
...
07:53:37.322 [main] INFO  org.apache.pulsar.broker.PulsarService - messaging service is ready, bootstrap service port = 8080, broker url= pulsar://localhost:6650, cluster=standalone, configs=org.apache.pulsar.broker.ServiceConfiguration@98b63c1
...

팁:

  • 상태 확인을 하려면 bin/pulsar-admin brokers healthcheck 명령을 사용할 수 있어요. 자세한 내용은 Pulsar admin 문서를 참고해요.
  • 로컬 standalone 클러스터를 시작하면 public/default 네임스페이스가 자동으로 생성돼요. 이 네임스페이스는 개발 목적용이에요. 모든 Pulsar 토픽은 네임스페이스 안에서 관리돼요. 자세한 내용은 토픽 문서를 참고해요.

2단계: Docker에서 Pulsar 사용하기 (Use Pulsar in Docker)

Pulsar는 Java, Go, Python, C++ 같은 다양한 클라이언트 라이브러리를 제공해요.

로컬 standalone 클러스터를 실행 중이라면, 다음 루트 URL 중 하나를 사용해 클러스터와 상호작용할 수 있어요.

  • pulsar://localhost:6650
  • http://localhost:8080

다음 예시는 Python 클라이언트 API로 Pulsar를 시작해 보는 방법을 안내해요.

PyPI에서 Pulsar Python 클라이언트 라이브러리를 직접 설치해요.

pip install pulsar-client

메시지 소비 (Consume a message)

컨슈머를 만들고 토픽을 구독해요.

import pulsar

client = pulsar.Client('pulsar://localhost:6650')
consumer = client.subscribe('my-topic', subscription_name='my-sub')

while True:
    msg = consumer.receive()
    print("Received message: '%s'" % msg.data())
    consumer.acknowledge(msg)

client.close()

메시지 생산 (Produce a message)

몇 개의 테스트 메시지를 보낼 프로듀서를 시작해요.

import pulsar

client = pulsar.Client('pulsar://localhost:6650')
producer = client.create_producer('my-topic')

for i in range(10):
    producer.send(('hello-pulsar-%d' % i).encode('utf-8'))

client.close()

3단계: 토픽 통계 가져오기 (Get the topic statistics)

Pulsar에서는 REST API, Java, 또는 명령줄 도구를 사용해 시스템의 모든 측면을 제어할 수 있어요. API에 대한 자세한 내용은 Admin API 개요를 참고해요.

가장 간단한 예시로, curl을 사용해 특정 토픽의 통계를 확인할 수 있어요.

curl http://localhost:8080/admin/v2/persistent/public/default/my-topic/stats | python -m json.tool

출력은 다음과 비슷해요.

{
    "msgRateIn": 0.0,
    "msgThroughputIn": 0.0,
    "msgRateOut": 1.8332950480217471,
    "msgThroughputOut": 91.33142602871978,
    "bytesInCounter": 7097,
    "msgInCounter": 143,
    "bytesOutCounter": 6607,
    "msgOutCounter": 133,
    "averageMsgSize": 0.0,
    "msgChunkPublished": false,
    "storageSize": 7097,
    "backlogSize": 0,
    "offloadedStorageSize": 0,
    "publishers": [
        {
            "accessMode": "Shared",
            "msgRateIn": 0.0,
            "msgThroughputIn": 0.0,
            "averageMsgSize": 0.0,
            "chunkedMessageRate": 0.0,
            "producerId": 0,
            "metadata": {},
            "address": "/127.0.0.1:35604",
            "connectedSince": "2021-07-04T09:05:43.04788Z",
            "clientVersion": "2.8.0",
            "producerName": "standalone-2-5"
        }
    ],
    "waitingPublishers": 0,
    "subscriptions": {
        "my-sub": {
            "msgRateOut": 1.8332950480217471,
            "msgThroughputOut": 91.33142602871978,
            "bytesOutCounter": 6607,
            "msgOutCounter": 133,
            "msgRateRedeliver": 0.0,
            "chunkedMessageRate": 0,
            "msgBacklog": 0,
            "backlogSize": 0,
            "msgBacklogNoDelayed": 0,
            "blockedSubscriptionOnUnackedMsgs": false,
            "msgDelayed": 0,
            "unackedMessages": 0,
            "type": "Exclusive",
            "activeConsumerName": "3c544f1daa",
            "msgRateExpired": 0.0,
            "totalMsgExpired": 0,
            "lastExpireTimestamp": 0,
            "lastConsumedFlowTimestamp": 1625389101290,
            "lastConsumedTimestamp": 1625389546070,
            "lastAckedTimestamp": 1625389546162,
            "lastMarkDeleteAdvancedTimestamp": 1625389546163,
            "consumers": [
                {
                    "msgRateOut": 1.8332950480217471,
                    "msgThroughputOut": 91.33142602871978,
                    "bytesOutCounter": 6607,
                    "msgOutCounter": 133,
                    "msgRateRedeliver": 0.0,
                    "chunkedMessageRate": 0.0,
                    "consumerName": "3c544f1daa",
                    "availablePermits": 867,
                    "unackedMessages": 0,
                    "avgMessagesPerEntry": 6,
                    "blockedConsumerOnUnackedMsgs": false,
                    "lastAckedTimestamp": 1625389546162,
                    "lastConsumedTimestamp": 1625389546070,
                    "metadata": {},
                    "address": "/127.0.0.1:35472",
                    "connectedSince": "2021-07-04T08:58:21.287682Z",
                    "clientVersion": "2.8.0"
                }
            ],
            "isDurable": true,
            "isReplicated": false,
            "allowOutOfOrderDelivery": false,
            "consumersAfterMarkDeletePosition": {},
            "nonContiguousDeletedMessagesRanges": 0,
            "nonContiguousDeletedMessagesRangesSerializedSize": 0,
            "durable": true,
            "replicated": false
        }
    },
    "replication": {},
    "deduplicationStatus": "Disabled",
    "nonContiguousDeletedMessagesRanges": 0,
    "nonContiguousDeletedMessagesRangesSerializedSize": 0
}

더 알아보기 (Learn more)

  • Docker Compose로 다중 노드 클러스터를 띄우는 방법은 Docker Compose 시작 문서를 참고해요.
  • Pulsar 클라이언트 라이브러리 사용법은 클라이언트 라이브러리 문서를 살펴보세요.
  • Admin API 개요가 궁금하다면 Admin API 문서를 참고해요.