게시 오류는 일반적으로 서비스 CPU 부족, 잘못된 스레드 상태, 네트워크 정체 등의 클라이언트 측 병목 현상으로 인해 발생합니다. 게시자 재시도 정책은 timesPub/Sub의 메시지 전송 재시도 횟수와 각 재시도 사이의 시간 길이를 정의합니다.
이 문서에서는 주제에 게시된 메시지에 재시도 요청을 사용하는 것과 관련된 정보를 제공합니다.
시작하기 전에
게시 워크플로를 구성하기 전에 다음 작업이 완료되어야 합니다.
필요한 역할
주제에 메시지 요청을 재시도하는 데 필요한 권한을 얻으려면 관리자에게 주제에 대한 Pub/Sub 게시자(roles/pubsub.publisher
) IAM 역할을 부여해 달라고 요청하세요.
역할 부여에 대한 자세한 내용은 액세스 관리를 참조하세요.
커스텀 역할이나 다른 사전 정의된 역할을 통해 필요한 권한을 얻을 수도 있습니다.
주제 및 구독을 만들거나 업데이트하려면 추가 권한이 필요합니다.
재시도 요청 정보
재시도 설정은 Pub/Sub 클라이언트 라이브러리가 게시 요청을 재시도하는 방법을 제어합니다. 클라이언트 라이브러리에 포함되는 재시도 설정은 다음과 같습니다.
- 초기 요청 제한 시간: 초기 게시 요청이 완료될 때까지 기다리는 클라이언트 라이브러리가 대기를 중지하기 전까지의 시간입니다.
- 재시도 지연: 클라이언트 라이브러리가 요청 재시도를 위해 기다리는 요청 제한 시간이 지난 후의 경과 시간입니다.
- 총 제한 시간: 클라이언트 라이브러리가 요청 게시 재시도를 중지한 후 경과한 시간입니다.
게시 요청을 재시도하려면 초기 요청 제한 시간이 총 제한 시간보다 짧아야 합니다. 예를 들어 지수 백오프를 사용하는 경우 클라이언트 라이브러리가 다음과 같이 요청 제한 시간 및 재시도 지연을 계산합니다.
- 각 게시 요청이 지나면 최대 요청 제한 시간까지 요청 제한 시간의 배수로 요청 제한 시간이 늘어납니다.
- 재시도할 때마다 재시도 지연은 최대 재시도 지연까지 재시도 지연의 배수로 증가합니다.
메시지 요청 재시도
게시 프로세스 중에 일시적이거나 영구적인 게시 오류가 발생할 수 있습니다. 일시적인 오류의 경우 일반적으로 Pub/Sub가 메시지를 자동으로 다시 시도하므로 별도로 조치를 취할 필요가 없습니다.
게시 작업이 성공했지만 게시자 클라이언트에서 게시 응답을 제때 수신하지 못할 때도 오류가 발생할 수 있습니다. 이 경우에도 게시 작업이 다시 시도됩니다. 따라서 메시지 ID가 다른 동일한 메시지가 두 개 있을 수 있습니다.
지속적인 오류가 발생하면 Pub/Sub 과부하를 방지하기 위해 게시 프로세스 외부에서 적절한 조치를 구현하는 것이 좋습니다.
재시도를 보증할 수 없는 오류를 제외하고, 실패한 게시는 자동으로 다시 시도됩니다. 본 샘플 코드는 커스텀 재시도 설정을 적용한 게시자 생성 방법을 보여줍니다. 커스텀 재시도 설정을 지원하지 않는 클라이언트 라이브러리도 있습니다. 자세한 내용은 선택한 언어의 API 참조 문서에서 확인하세요.
Node.js
이 샘플을 시도하기 전에 빠른 시작: 클라이언트 라이브러리 사용의 Node.js 설정 안내를 따르세요.
자세한 내용은 Pub/Sub Node.js API 참고 문서를 참조하세요.
/**
* TODO(developer): Uncomment these variables before running the sample.
*/
// const projectId = 'YOUR_PROJECT_ID'
// const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID';
// const data = JSON.stringify({foo: 'bar'});
// Imports the Google Cloud client library. v1 is for the lower level
// proto access.
const {v1} = require('@google-cloud/pubsub');
// Creates a publisher client.
const publisherClient = new v1.PublisherClient({
// optional auth parameters
});
async function publishWithRetrySettings(projectId, topicNameOrId, data) {
const formattedTopic = publisherClient.projectTopicPath(
projectId,
topicNameOrId
);
// Publishes the message as a string, e.g. "Hello, world!" or JSON.stringify(someObject)
const dataBuffer = Buffer.from(data);
const messagesElement = {
data: dataBuffer,
};
const messages = [messagesElement];
// Build the request
const request = {
topic: formattedTopic,
messages: messages,
};
// Retry settings control how the publisher handles retryable failures. Default values are shown.
// The `retryCodes` array determines which grpc errors will trigger an automatic retry.
// The `backoffSettings` object lets you specify the behaviour of retries over time.
const retrySettings = {
retryCodes: [
10, // 'ABORTED'
1, // 'CANCELLED',
4, // 'DEADLINE_EXCEEDED'
13, // 'INTERNAL'
8, // 'RESOURCE_EXHAUSTED'
14, // 'UNAVAILABLE'
2, // 'UNKNOWN'
],
backoffSettings: {
// The initial delay time, in milliseconds, between the completion
// of the first failed request and the initiation of the first retrying request.
initialRetryDelayMillis: 100,
// The multiplier by which to increase the delay time between the completion
// of failed requests, and the initiation of the subsequent retrying request.
retryDelayMultiplier: 1.3,
// The maximum delay time, in milliseconds, between requests.
// When this value is reached, retryDelayMultiplier will no longer be used to increase delay time.
maxRetryDelayMillis: 60000,
// The initial timeout parameter to the request.
initialRpcTimeoutMillis: 5000,
// The multiplier by which to increase the timeout parameter between failed requests.
rpcTimeoutMultiplier: 1.0,
// The maximum timeout parameter, in milliseconds, for a request. When this value is reached,
// rpcTimeoutMultiplier will no longer be used to increase the timeout.
maxRpcTimeoutMillis: 600000,
// The total time, in milliseconds, starting from when the initial request is sent,
// after which an error will be returned, regardless of the retrying attempts made meanwhile.
totalTimeoutMillis: 600000,
},
};
const [response] = await publisherClient.publish(request, {
retry: retrySettings,
});
console.log(`Message ${response.messageIds} published.`);
}
Node.js
이 샘플을 시도하기 전에 빠른 시작: 클라이언트 라이브러리 사용의 Node.js 설정 안내를 따르세요.
자세한 내용은 Pub/Sub Node.js API 참고 문서를 참조하세요.
/**
* TODO(developer): Uncomment these variables before running the sample.
*/
// const projectId = 'YOUR_PROJECT_ID'
// const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID';
// const data = JSON.stringify({foo: 'bar'});
// Imports the Google Cloud client library. v1 is for the lower level
// proto access.
import {v1} from '@google-cloud/pubsub';
// Creates a publisher client.
const publisherClient = new v1.PublisherClient({
// optional auth parameters
});
async function publishWithRetrySettings(
projectId: string,
topicNameOrId: string,
data: string
) {
const formattedTopic = publisherClient.projectTopicPath(
projectId,
topicNameOrId
);
// Publishes the message as a string, e.g. "Hello, world!" or JSON.stringify(someObject)
const dataBuffer = Buffer.from(data);
const messagesElement = {
data: dataBuffer,
};
const messages = [messagesElement];
// Build the request
const request = {
topic: formattedTopic,
messages: messages,
};
// Retry settings control how the publisher handles retryable failures. Default values are shown.
// The `retryCodes` array determines which grpc errors will trigger an automatic retry.
// The `backoffSettings` object lets you specify the behaviour of retries over time.
const retrySettings = {
retryCodes: [
10, // 'ABORTED'
1, // 'CANCELLED',
4, // 'DEADLINE_EXCEEDED'
13, // 'INTERNAL'
8, // 'RESOURCE_EXHAUSTED'
14, // 'UNAVAILABLE'
2, // 'UNKNOWN'
],
backoffSettings: {
// The initial delay time, in milliseconds, between the completion
// of the first failed request and the initiation of the first retrying request.
initialRetryDelayMillis: 100,
// The multiplier by which to increase the delay time between the completion
// of failed requests, and the initiation of the subsequent retrying request.
retryDelayMultiplier: 1.3,
// The maximum delay time, in milliseconds, between requests.
// When this value is reached, retryDelayMultiplier will no longer be used to increase delay time.
maxRetryDelayMillis: 60000,
// The initial timeout parameter to the request.
initialRpcTimeoutMillis: 5000,
// The multiplier by which to increase the timeout parameter between failed requests.
rpcTimeoutMultiplier: 1.0,
// The maximum timeout parameter, in milliseconds, for a request. When this value is reached,
// rpcTimeoutMultiplier will no longer be used to increase the timeout.
maxRpcTimeoutMillis: 600000,
// The total time, in milliseconds, starting from when the initial request is sent,
// after which an error will be returned, regardless of the retrying attempts made meanwhile.
totalTimeoutMillis: 600000,
},
};
const [response] = await publisherClient.publish(request, {
retry: retrySettings,
});
console.log(`Message ${response.messageIds} published.`);
}
순서 키를 사용하여 요청 재시도
단일 게시자 클라이언트가 있다고 가정합니다. Pub/Sub 클라이언트 라이브러리를 사용하여 동일한 순서 키 A에 대해 메시지 1, 2, 3을 게시합니다. 이제 RPC 기한이 만료되기 전에 메시지 1에 대해 게시된 응답이 게시자 클라이언트에서 수신되지 않는다고 가정해 보겠습니다. 메시지 1을 다시 게시해야 합니다. 메시지 1이 성공적으로 완료된 후에만 메시지 2가 게시되었다고 가정할 경우 구독자 클라이언트에서 수신된 메시지 순서는 1, 1, 2, 3이 됩니다. 게시된 각 메시지에는 고유한 메시지 ID가 있습니다. 구독자 클라이언트의 관점에서 4개의 메시지가 게시되었으며 처음 2개의 메시지는 동일한 내용을 갖습니다.
순서 키로 게시 요청을 재시도하는 것도 일괄 설정으로 인해 복잡할 수 있습니다. 클라이언트 라이브러리는 더 효율적인 게시를 위해 메시지를 일괄 처리합니다. 이전 예시를 계속 진행하여 메시지 1과 2가 일괄 처리된다고 가정해 보겠습니다. 이 배치는 단일 요청으로 서버에 전송됩니다. 서버가 제시간에 응답을 반환하지 않으면 게시자 클라이언트가 이 두 메시지 배치를 다시 시도합니다. 따라서 구독자 클라이언트는 메시지 1, 2, 1, 2, 3을 수신할 수 있습니다. 메시지를 순서대로 게시하기 위해 Pub/Sub 클라이언트 라이브러리를 사용하고 게시 작업이 실패하면 동일한 순서 키의 나머지 모든 메시지에 대한 게시 작업이 실패합니다. 그러면 게시자 클라이언트는 다음 작업 중 하나를 따르기로 결정할 수 있습니다.
다시 시도할 수 없는 오류가 발생하면 클라이언트 라이브러리는 메시지를 게시하지 않으며 동일한 순서 키가 포함된 다른 메시지의 게시를 중지합니다. 예를 들어 게시자가 존재하지 않는 주제에 메시지를 보내면 다시 시도할 수 없는 오류가 발생합니다. 동일한 순서 키가 포함된 메시지 게시를 계속하려면 게시를 재개하는 메서드를 호출한 다음 게시를 다시 시작합니다.
다음 샘플에서는 동일한 순서 키가 포함된 메시지의 게시를 재개하는 방법을 보여줍니다.
다음 단계
고급 게시 옵션을 구성하는 방법은 다음을 참조하세요.