Node.js 클라이언트 사용

Node.js 클라이언트 사용 (Use a Node.js client)

Pulsar Node.js 클라이언트로 프로듀서, 컨슈머, 리더를 실제로 만들어 메시지를 주고받는 방법을 살펴볼게요. 각 개체를 만들 때 구성 객체를 넘기고, 사용 가능한 연산 메서드들을 정리했어요. 마지막에는 리더가 컨슈머와 어떻게 다른지도 확인할 수 있어요.

출처: 문서

본문

프로듀서 만들기 (Create a producer)

프로듀서 구성 객체를 사용해 Node.js 프로듀서를 구성할 수 있어요.

예시는 다음과 같아요.

const producer = await client.createProducer({
  topic: 'my-topic', // or 'my-tenant/my-namespace/my-topic' to specify topic's tenant and namespace
});

await producer.send({
  data: Buffer.from("Hello, Pulsar"),
});

await producer.close();

새 Pulsar 프로듀서를 만들면 연산이 Promise 객체를 반환하고, executor 함수를 통해 프로듀서 인스턴스나 오류를 얻어요. 위 예시에서는 executor 함수 대신 await 연산자를 사용했어요.

프로듀서 연산 (Producer operations)

Pulsar Node.js 프로듀서에는 다음 메서드가 있어요.

메서드 설명 반환 타입
send(Object) 프로듀서의 토픽에 메시지를 게시해요. 메시지가 Pulsar 브로커에 성공적으로 ack되거나 오류가 던져지면, 결과가 메시지 ID인 Promise 객체가 executor 함수를 실행해요. Promise<Object>
flush() send 큐에서 Pulsar 브로커로 메시지를 보내요. 메시지가 Pulsar 브로커에 성공적으로 ack되거나 오류가 던져지면, Promise 객체가 executor 함수를 실행해요. Promise<null>
close() 프로듀서를 닫고 할당된 모든 리소스를 해제해요. close()가 호출되면 게시자로부터 더 이상 메시지를 받지 않아요. 이 메서드는 Promise 객체를 반환해요. 모든 보류 중인 게시 요청이 Pulsar에 영속화되면 executor 함수를 실행해요. 오류가 던져지면 보류 중인 쓰기는 재시도되지 않아요. Promise<null>
getProducerName() 프로듀서 이름의 getter 메서드. string
getTopic() 토픽 이름의 getter 메서드. string

프로듀서 예시 (Producer example)

이 예시는 my-topic 토픽에 Node.js 프로듀서를 만들고 10개의 메시지를 그 토픽에 보내요.

const Pulsar = require('pulsar-client');

(async () => {
  // Create a client
  const client = new Pulsar.Client({
    serviceUrl: 'pulsar://localhost:6650',
  });

  // Create a producer
  const producer = await client.createProducer({
    topic: 'my-topic',
  });

  // Send messages
  for (let i = 0; i < 10; i += 1) {
    const msg = `my-message-${i}`;
    producer.send({
      data: Buffer.from(msg),
    });
    console.log(`Sent message: ${msg}`);
  }
  await producer.flush();

  await producer.close();
  await client.close();
})();

컨슈머 만들기 (Create a consumer)

컨슈머 구성 객체를 사용해 Node.js 컨슈머를 구성할 수 있어요.

예시는 다음과 같아요.

const consumer = await client.subscribe({
  topic: 'my-topic',
  subscription: 'my-subscription',
});

const msg = await consumer.receive();
console.log(msg.getData().toString());
consumer.acknowledge(msg);

await consumer.close();

새 Pulsar 컨슈머를 만들면 연산이 Promise 객체를 반환하고, executor 함수를 통해 컨슈머 인스턴스나 오류를 얻어요. 이 예시에서는 executor 함수 대신 await 연산자를 사용했어요.

컨슈머 연산 (Consumer operations)

Pulsar Node.js 컨슈머에는 다음 메서드가 있어요.

메서드 설명 반환 타입
receive() 토픽에서 단일 메시지를 받아요. 메시지가 사용 가능해지면 Promise 객체가 executor 함수를 실행하고 메시지 객체를 얻어요. Promise<Object>
receive(Number) 특정 타임아웃(밀리초)으로 토픽에서 단일 메시지를 받아요. Promise<Object>
acknowledge(Object) 메시지 객체로 Pulsar 브로커에 메시지를 ack해요. void
acknowledgeId(Object) 메시지 ID 객체로 Pulsar 브로커에 메시지를 ack해요. void
acknowledgeCumulative(Object) 지정된 메시지를 포함해 그때까지 스트림의 모든 메시지를 ack해요. acknowledgeCumulative 메서드는 void를 반환하고 ack를 브로커에 비동기로 보내요. 그 후 메시지는 컨슈머에게 재전달되지 않아요. 누적 ack는 공유(shared) 서브스크립션 타입과 함께 사용할 수 없어요. void
acknowledgeCumulativeId(Object) 지정된 메시지 ID를 포함해 그때까지 스트림의 모든 메시지를 ack해요. void
negativeAcknowledge(Message) 메시지 객체로 Pulsar 브로커에 메시지를 부정 ack해요. void
negativeAcknowledgeId(MessageId) 메시지 ID 객체로 Pulsar 브로커에 메시지를 부정 ack해요. void
close() 컨슈머를 닫아 브로커에서 메시지를 받는 기능을 비활성화해요. Promise<null>
unsubscribe() 서브스크립션을 구독 해제해요. Promise<null>

컨슈머 예시 (Consumer example)

이 예시는 my-topic 토픽에 my-subscription 서브스크립션으로 Node.js 컨슈머를 만들고, 메시지를 받아 도착하는 내용을 출력한 다음 각 메시지를 Pulsar 브로커에 10번 ack해요.

const Pulsar = require('pulsar-client');

(async () => {
  // Create a client
  const client = new Pulsar.Client({
    serviceUrl: 'pulsar://localhost:6650',
  });

  // Create a consumer
  const consumer = await client.subscribe({
    topic: 'my-topic',
    subscription: 'my-subscription',
    subscriptionType: 'Exclusive',
  });

  // Receive messages
  for (let i = 0; i < 10; i += 1) {
    const msg = await consumer.receive();
    console.log(msg.getData().toString());
    consumer.acknowledge(msg);
  }

  await consumer.close();
  await client.close();
})();

대신 컨슈머를 리스너와 함께 만들어 메시지를 처리할 수도 있어요.

// Create a consumer
const consumer = await client.subscribe({
  topic: 'my-topic',
  subscription: 'my-subscription',
  subscriptionType: 'Exclusive',
  listener: (msg, msgConsumer) => {
    console.log(msg.getData().toString());
    msgConsumer.acknowledge(msg);
  },
});

Pulsar Node.js 클라이언트는 AsyncWorker를 사용해요. 컨슈머/프로듀서 만들기, 메시지 수신/송신 같은 비동기 연산은 워커 스레드에서 수행돼요. 이 연산들이 완료될 때까지 워커 스레드는 블록돼요.

기본적으로 워커 스레드가 4개뿐이라 호출된 메서드가 끝나지 않을 수 있어요. 이 상황을 피하려면 UV_THREADPOOL_SIZE를 설정해 워커 스레드 수를 늘리거나, receive()를 여러 번 호출하는 대신 리스너를 정의하세요.

리더 만들기 (Create a reader)

Pulsar 리더는 스트림에서 어떤 메시지부터 시작할지 명시적으로 지정해야 한다는 점에서 컨슈머와 달라요(반면 컨슈머는 자동으로 가장 최근의 unacked 메시지부터 시작해요). 리더 구성 객체를 사용해 Node.js 리더를 구성할 수 있어요.

예시는 다음과 같아요.

const reader = await client.createReader({
  topic: 'my-topic',
  startMessageId: Pulsar.MessageId.earliest(),
});

const msg = await reader.readNext();
console.log(msg.getData().toString());

await reader.close();

리더 연산 (Reader operations)

Pulsar Node.js 리더에는 다음 메서드가 있어요.

메서드 설명 반환 타입
readNext() 토픽에서 다음 메시지를 받아요(컨슈머의 receive 메서드와 유사). 메시지가 사용 가능해지면 Promise 객체가 executor 함수를 실행하고 메시지 객체를 얻어요. Promise<Object>
readNext(Number) 특정 타임아웃(밀리초)으로 토픽에서 단일 메시지를 받아요. Promise<Object>
hasNext() 대상 토픽에 브로커가 다음 메시지를 갖고 있는지 반환해요. Boolean
close() 리더를 닫아 브로커에서 메시지를 받는 기능을 비활성화해요. Promise<null>

리더 예시 (Reader example)

이 예시는 my-topic 토픽으로 Node.js 리더를 만들고, 메시지를 읽어 도착하는 내용을 10번 출력해요.

const Pulsar = require('pulsar-client');

(async () => {
  // Create a client
  const client = new Pulsar.Client({
    serviceUrl: 'pulsar://localhost:6650',
    operationTimeoutSeconds: 30,
  });

  // Create a reader
  const reader = await client.createReader({
    topic: 'my-topic',
    startMessageId: Pulsar.MessageId.earliest(),
  });

  // read messages
  for (let i = 0; i < 10; i += 1) {
    const msg = await reader.readNext();
    console.log(msg.getData().toString());
  }

  await reader.close();
  await client.close();
})();

더 알아보기 (Learn more)