無效信件主題

訂閱者可能因為各種原因無法處理訊息。舉例來說,擷取處理訊息所需資料時,可能會發生暫時性問題。或者,訊息格式與訂閱者預期不符。

如要管理訂閱者無法確認的無法傳送訊息,Pub/Sub 可以將這些訊息轉送至無效信件主題 (也稱為無效信件佇列)。

事前準備

  • 為無法傳送訊息的主題設定建立主題

    或者,如果您按照本頁面的所有指示操作,可以在後續步驟中建立主題。

必要的角色

如要取得管理主題和訂閱項目所需的權限,請要求管理員授予您專案的「Pub/Sub 編輯者」 (roles/pubsub.editor) 身分與存取權管理角色。如要進一步瞭解如何授予角色,請參閱「管理專案、資料夾和機構的存取權」。

您或許還可透過自訂角色或其他預先定義的角色取得必要權限。

您可以在專案層級和個別資源層級設定存取權控管。您可以在一個專案中建立訂閱項目,並附加至位於其他專案的主題。請確認您具備各專案的必要權限。

無效信件主題的運作方式

如果訂閱者應用程式無法確認訊息,Pub/Sub 會重試傳送,直到確認期限到期或訊息過期為止。在嘗試傳送訊息的次數達到設定上限後,Pub/Sub 可以將無法傳送的訊息轉送至無效信件主題。

Pub/Sub 轉寄無法傳送的訊息時,會將原始訊息包裝在新訊息中,並新增屬性來識別來源訂閱項目。然後將訊息傳送至指定的無效信件主題。附加至無效信件主題的個別訂閱項目隨後會收到這些轉寄訊息,以供分析和離線偵錯。

傳送嘗試次數上限的計算方式

只有在無效信件主題設定正確,且包含正確的身分與存取權管理權限時,Pub/Sub 才會計算傳送嘗試次數。

傳送嘗試次數上限為近似值,因為 Pub/Sub 會盡力轉送無法傳送的訊息。服務可能會在嘗試次數少於設定次數後轉寄郵件,也可能在轉寄前多嘗試幾次。

訊息的傳送嘗試次數也可能會重設為零,尤其是具有非使用中訂閱者的提取訂閱項目。因此,訊息傳送至訂閱端用戶端的次數,可能會超過設定的傳送嘗試次數上限。

無效信件主題屬性

您可以在死信主題上設定下列訂閱屬性。

  • 嘗試傳送次數上限:數值,代表 Pub/Sub 嘗試傳送特定訊息的次數。如果訂閱端在設定的傳送嘗試次數內無法確認訊息,系統就會將訊息轉送至無效信件主題。

    • 預設值 = 5
    • 最大值 = 100
    • 最小值 = 5
  • 含有無效信件主題的專案:如果無效信件主題與訂閱項目位於不同專案,您必須指定含有無效信件主題的專案。將無效信件主題設為與訂閱項目附加的主題不同的主題。

設定無效信件主題

以下步驟說明如何使用無法傳送訊息的主題。

  1. 建立主題 (做為無法傳送訊息的主題)。

  2. 為無效信件主題建立訂閱項目。

  3. 在訂閱項目上啟用無效信件

  4. 將先前建立的主題附加至訂閱項目。

  5. 將使用死信主題所需的角色授予 Pub/Sub 服務帳戶。

建立要搭配無效信件主題使用的主題

如果您已建立要用於訂閱的主題,可以略過這個步驟。

  1. 前往 Google Cloud 控制台的「主題」頁面。

    前往「主題」

  2. 按一下「建立主題」

  3. 輸入主題 ID,例如 my-test-topic

  4. 保留預設訂閱方案的選項,然後按一下「建立」

為訂閱項目設定無效信件主題

您可以在新訂閱項目或現有訂閱項目中設定死信主題。

為新訂閱項目設定無效信件主題

您可以使用Google Cloud 控制台、Google Cloud CLI、用戶端程式庫或 Pub/Sub API,建立訂閱項目並設定無法傳送的訊息主題。

控制台

如要建立訂閱項目並設定無法傳送的訊息主題,請完成下列步驟:

  1. 前往 Google Cloud 控制台的「Subscriptions」(訂閱項目) 頁面。

    前往「訂閱項目」頁面

  2. 按一下「Create Subscription」 (建立訂閱項目)

  3. 輸入「Subscription ID」(訂閱項目 ID)

  4. 選擇要透過訂閱方案使用的內容。訂閱項目會接收主題中的訊息。這不是無效信件主題。 您將在下一個步驟中選擇。

  5. 在「無效信件」部分,選取「啟用無效信件」

  6. 從下拉式選單中選擇無效信件主題。

    如果所選無效信件主題沒有訂閱項目,系統會提示您建立訂閱項目。

  7. 在「傳送嘗試次數上限」欄位中,指定介於 5 至 100 之間的整數。

  8. 點選「建立」

  9. 按一下「詳細資料」面板,找出所有可能的動作項目。如果任何項目顯示錯誤圖示 ,請按一下動作項目來解決問題。

    「Dead Lettering」分頁,其中包含一些待辦事項。

gcloud

如要建立訂閱並設定死信主題,請使用 gcloud pubsub subscriptions create 指令:

gcloud pubsub subscriptions create subscription-id \   --topic=topic-id \   --dead-letter-topic=dead-letter-topic-name \   [--max-delivery-attempts=max-delivery-attempts] \   [--dead-letter-topic-project=dead-letter-topic-project]

C++

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 C++ 設定操作說明進行操作。詳情請參閱 Pub/Sub C++ API 參考說明文件

namespace pubsub = ::google::cloud::pubsub; namespace pubsub_admin = ::google::cloud::pubsub_admin; [](pubsub_admin::SubscriptionAdminClient client,    std::string const& project_id, std::string const& topic_id,    std::string const& subscription_id,    std::string const& dead_letter_topic_id,    int dead_letter_delivery_attempts) {   google::pubsub::v1::Subscription request;   request.set_name(       pubsub::Subscription(project_id, subscription_id).FullName());   request.set_topic(pubsub::Topic(project_id, topic_id).FullName());   request.mutable_dead_letter_policy()->set_dead_letter_topic(       pubsub::Topic(project_id, dead_letter_topic_id).FullName());   request.mutable_dead_letter_policy()->set_max_delivery_attempts(       dead_letter_delivery_attempts);   auto sub = client.CreateSubscription(request);   if (sub.status().code() == google::cloud::StatusCode::kAlreadyExists) {     std::cout << "The subscription already exists\n";     return;   }   if (!sub) throw std::move(sub).status();    std::cout << "The subscription was successfully created: "             << sub->DebugString() << "\n";    std::cout << "It will forward dead letter messages to: "             << sub->dead_letter_policy().dead_letter_topic() << "\n";    std::cout << "After " << sub->dead_letter_policy().max_delivery_attempts()             << " delivery attempts.\n"; }

C#

在嘗試這個範例之前,請先按照快速入門:使用用戶端程式庫中的 C# 設定操作說明進行操作。詳情請參閱 Pub/Sub C# API 參考說明文件

 using Google.Cloud.PubSub.V1; using System;  public class CreateSubscriptionWithDeadLetterPolicySample {     public Subscription CreateSubscriptionWithDeadLetterPolicy(string projectId, string topicId, string subscriptionId, string deadLetterTopicId)     {         SubscriberServiceApiClient subscriber = SubscriberServiceApiClient.Create();         // This is the subscription you want to create with a dead letter policy.         var subscriptionName = SubscriptionName.FromProjectSubscription(projectId, subscriptionId);         // This is an existing topic that you want to attach the subscription with dead letter policy to.         var topicName = TopicName.FromProjectTopic(projectId, topicId);         // This is an existing topic that the subscription with dead letter policy forwards dead letter messages to.         var deadLetterTopic = TopicName.FromProjectTopic(projectId, deadLetterTopicId).ToString();         var subscriptionRequest = new Subscription         {             SubscriptionName = subscriptionName,             TopicAsTopicName = topicName,             DeadLetterPolicy = new DeadLetterPolicy             {                 DeadLetterTopic = deadLetterTopic,                 // The maximum number of times that the service attempts to deliver a                 // message before forwarding it to the dead letter topic. Must be [5-100].                 MaxDeliveryAttempts = 10             },             AckDeadlineSeconds = 30         };          var subscription = subscriber.CreateSubscription(subscriptionRequest);         Console.WriteLine("Created subscription: " + subscription.SubscriptionName.SubscriptionId);         Console.WriteLine($"It will forward dead letter messages to: {subscription.DeadLetterPolicy.DeadLetterTopic}");         Console.WriteLine($"After {subscription.DeadLetterPolicy.MaxDeliveryAttempts} delivery attempts.");         // Remember to attach a subscription to the dead letter topic because         // messages published to a topic with no subscriptions are lost.         return subscription;     } }

Go

以下範例使用 Go Pub/Sub 用戶端程式庫的主要版本 (v2)。如果您仍在使用第 1 版程式庫,請參閱第 2 版遷移指南。如要查看第 1 版程式碼範例清單,請參閱 已淘汰的程式碼範例

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的操作說明設定 Go 環境。詳情請參閱 Pub/Sub Go API 參考說明文件

import ( 	"context" 	"fmt" 	"io"  	"cloud.google.com/go/pubsub/v2" 	"cloud.google.com/go/pubsub/v2/apiv1/pubsubpb" )  // createSubWithDeadLetter creates a subscription with a dead letter policy. func createSubWithDeadLetter(w io.Writer, projectID, topic, subscription, fullyQualifiedDeadLetterTopic string) error { 	// projectID := "my-project-id" 	// topic := "projects/my-project-id/topics/my-topic" 	// subscription := "projects/my-project-id/subscriptions/my-sub" 	// fullyQualifiedDeadLetterTopic := "projects/my-project-id/topics/my-dead-letter-topic" 	ctx := context.Background() 	client, err := pubsub.NewClient(ctx, projectID) 	if err != nil { 		return fmt.Errorf("pubsub.NewClient: %w", err) 	} 	defer client.Close()  	_, err = client.SubscriptionAdminClient.CreateSubscription(ctx, &pubsubpb.Subscription{ 		Name:  subscription, 		Topic: topic, 		DeadLetterPolicy: &pubsubpb.DeadLetterPolicy{ 			DeadLetterTopic:     fullyQualifiedDeadLetterTopic, 			MaxDeliveryAttempts: 10, 		}, 	}) 	if err != nil { 		return fmt.Errorf("CreateSubscription: %w", err) 	} 	fmt.Fprintf(w, "Created subscription with dead letter topic: (%s)\n", fullyQualifiedDeadLetterTopic) 	fmt.Fprintln(w, "To process dead letter messages, remember to add a subscription to your dead letter topic.") 	return nil } 

Java

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Java 設定操作說明進行操作。詳情請參閱 Pub/Sub Java API 參考說明文件

import com.google.cloud.pubsub.v1.SubscriptionAdminClient; import com.google.pubsub.v1.DeadLetterPolicy; import com.google.pubsub.v1.ProjectSubscriptionName; import com.google.pubsub.v1.ProjectTopicName; import com.google.pubsub.v1.Subscription; import java.io.IOException;  public class CreateSubscriptionWithDeadLetterPolicyExample {    public static void main(String... args) throws Exception {     // TODO(developer): Replace these variables before running the sample.     String projectId = "your-project-id";     // This is the subscription you want to create with a dead letter policy.     String subscriptionId = "your-subscription-id";     // This is an existing topic that you want to attach the subscription with dead letter policy     // to.     String topicId = "your-topic-id";     // This is an existing topic that the subscription with dead letter policy forwards dead letter     // messages to.     String deadLetterTopicId = "your-dead-letter-topic-id";      CreateSubscriptionWithDeadLetterPolicyExample.createSubscriptionWithDeadLetterPolicyExample(         projectId, subscriptionId, topicId, deadLetterTopicId);   }    public static void createSubscriptionWithDeadLetterPolicyExample(       String projectId, String subscriptionId, String topicId, String deadLetterTopicId)       throws IOException {     try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {        ProjectTopicName topicName = ProjectTopicName.of(projectId, topicId);       ProjectSubscriptionName subscriptionName =           ProjectSubscriptionName.of(projectId, subscriptionId);       ProjectTopicName deadLetterTopicName = ProjectTopicName.of(projectId, deadLetterTopicId);        DeadLetterPolicy deadLetterPolicy =           DeadLetterPolicy.newBuilder()               .setDeadLetterTopic(deadLetterTopicName.toString())               // The maximum number of times that the service attempts to deliver a               // message before forwarding it to the dead letter topic. Must be [5-100].               .setMaxDeliveryAttempts(10)               .build();        Subscription request =           Subscription.newBuilder()               .setName(subscriptionName.toString())               .setTopic(topicName.toString())               .setDeadLetterPolicy(deadLetterPolicy)               .build();        Subscription subscription = subscriptionAdminClient.createSubscription(request);        System.out.println("Created subscription: " + subscription.getName());       System.out.println(           "It will forward dead letter messages to: "               + subscription.getDeadLetterPolicy().getDeadLetterTopic());       System.out.println(           "After "               + subscription.getDeadLetterPolicy().getMaxDeliveryAttempts()               + " delivery attempts.");       // Remember to attach a subscription to the dead letter topic because       // messages published to a topic with no subscriptions are lost.     }   } }

Node.js

在嘗試這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Node.js 設定說明進行操作。詳情請參閱 Pub/Sub Node.js API 參考說明文件

/**  * TODO(developer): Uncomment these variables before running the sample.  */ // const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID'; // const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID'; // const deadLetterTopicNameOrId = 'YOUR_DEAD_LETTER_TOPIC_NAME_OR_ID';  // Imports the Google Cloud client library const {PubSub} = require('@google-cloud/pubsub');  // Creates a client; cache this for further use const pubSubClient = new PubSub();  async function createSubscriptionWithDeadLetterPolicy(   topicNameOrId,   subscriptionNameOrId,   deadLetterTopicNameOrId, ) {   // Creates a new subscription   const options = {     deadLetterPolicy: {       deadLetterTopic: pubSubClient.topic(deadLetterTopicNameOrId).name,       maxDeliveryAttempts: 10,     },   };   await pubSubClient     .topic(topicNameOrId)     .createSubscription(subscriptionNameOrId, options);   console.log(     `Created subscription ${subscriptionNameOrId} with dead letter topic ${deadLetterTopicNameOrId}.`,   );   console.log(     'To process dead letter messages, remember to add a subscription to your dead letter topic.',   ); }

Node.js

在嘗試這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Node.js 設定說明進行操作。詳情請參閱 Pub/Sub Node.js API 參考說明文件

/**  * TODO(developer): Uncomment these variables before running the sample.  */ // const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID'; // const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID'; // const deadLetterTopicNameOrId = 'YOUR_DEAD_LETTER_TOPIC_NAME_OR_ID';  // Imports the Google Cloud client library import {PubSub, CreateSubscriptionOptions} from '@google-cloud/pubsub';  // Creates a client; cache this for further use const pubSubClient = new PubSub();  async function createSubscriptionWithDeadLetterPolicy(   topicNameOrId: string,   subscriptionNameOrId: string,   deadLetterTopicNameOrId: string, ) {   // Creates a new subscription   const options: CreateSubscriptionOptions = {     deadLetterPolicy: {       deadLetterTopic: pubSubClient.topic(deadLetterTopicNameOrId).name,       maxDeliveryAttempts: 10,     },   };   await pubSubClient     .topic(topicNameOrId)     .createSubscription(subscriptionNameOrId, options);   console.log(     `Created subscription ${subscriptionNameOrId} with dead letter topic ${deadLetterTopicNameOrId}.`,   );   console.log(     'To process dead letter messages, remember to add a subscription to your dead letter topic.',   ); }

PHP

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 PHP 設定說明進行操作。 詳情請參閱 Pub/Sub PHP API 參考說明文件

use Google\Cloud\PubSub\PubSubClient;  /**  * Creates a Pub/Sub subscription with dead letter policy enabled.  *  * @param string $projectId  The Google project ID.  * @param string $topicName  The Pub/Sub topic name.  * @param string $subscriptionName  The Pub/Sub subscription name.  * @param string $deadLetterTopicName The Pub/Sub topic to use for dead letter policy.  */ function dead_letter_create_subscription($projectId, $topicName, $subscriptionName, $deadLetterTopicName) {     $pubsub = new PubSubClient([         'projectId' => $projectId,     ]);      $topic = $pubsub->topic($topicName);     $deadLetterTopic = $pubsub->topic($deadLetterTopicName);      $subscription = $topic->subscribe($subscriptionName, [         'deadLetterPolicy' => [             'deadLetterTopic' => $deadLetterTopic         ]     ]);      printf(         'Subscription %s created with dead letter topic %s' . PHP_EOL,         $subscription->name(),         $deadLetterTopic->name()     ); }

Python

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Python 設定操作說明來進行。詳情請參閱 Pub/Sub Python API 參考說明文件

from google.cloud import pubsub_v1 from google.cloud.pubsub_v1.types import DeadLetterPolicy  # TODO(developer) # project_id = "your-project-id" # endpoint = "https://my-test-project.appspot.com/push" # TODO(developer): This is an existing topic that the subscription # with dead letter policy is attached to. # topic_id = "your-topic-id" # TODO(developer): This is an existing subscription with a dead letter policy. # subscription_id = "your-subscription-id" # TODO(developer): This is an existing dead letter topic that the subscription # with dead letter policy will forward dead letter messages to. # dead_letter_topic_id = "your-dead-letter-topic-id" # TODO(developer): This is the maximum number of delivery attempts allowed # for a message before it gets delivered to a dead letter topic. # max_delivery_attempts = 5  publisher = pubsub_v1.PublisherClient() subscriber = pubsub_v1.SubscriberClient()  topic_path = publisher.topic_path(project_id, topic_id) subscription_path = subscriber.subscription_path(project_id, subscription_id) dead_letter_topic_path = publisher.topic_path(project_id, dead_letter_topic_id)  dead_letter_policy = DeadLetterPolicy(     dead_letter_topic=dead_letter_topic_path,     max_delivery_attempts=max_delivery_attempts, )  with subscriber:     request = {         "name": subscription_path,         "topic": topic_path,         "dead_letter_policy": dead_letter_policy,     }     subscription = subscriber.create_subscription(request)  print(f"Subscription created: {subscription.name}") print(     f"It will forward dead letter messages to: {subscription.dead_letter_policy.dead_letter_topic}." ) print(     f"After {subscription.dead_letter_policy.max_delivery_attempts} delivery attempts." )

Ruby

以下範例使用 Ruby Pub/Sub 用戶端程式庫 v3。如果您仍在使用第 2 版程式庫,請參閱 第 3 版遷移指南。如要查看 Ruby 第 2 版程式碼範例清單,請參閱 已淘汰的程式碼範例

在試用這個範例之前,請先按照「快速入門:使用用戶端程式庫」的操作說明設定 Ruby 環境。詳情請參閱 Pub/Sub Ruby API 參考說明文件

Ruby

在試用這個範例之前,請先按照RubyPub/Sub 快速入門導覽課程:使用用戶端程式庫」中的操作說明進行設定。 詳情請參閱 Pub/Sub Ruby API 參考說明文件

如要驗證 Pub/Sub,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

# topic_id             = "your-topic-id" # subscription_id      = "your-subscription-id" # dead_letter_topic_id = "your-dead-letter-topic-id"  pubsub = Google::Cloud::PubSub.new subscription_admin = pubsub.subscription_admin  subscription = subscription_admin.create_subscription \   name: pubsub.subscription_path(subscription_id),   topic: pubsub.topic_path(topic_id),   dead_letter_policy: {     dead_letter_topic: pubsub.topic_path(dead_letter_topic_id),     max_delivery_attempts: 10   }  puts "Created subscription #{subscription_id} with dead letter topic " \      "#{dead_letter_topic_id}." puts "To process dead letter messages, remember to add a subscription to " \      "your dead letter topic."

為現有訂閱項目設定無效信件主題

您可以使用Google Cloud 控制台、gcloud CLI、用戶端程式庫或 Pub/Sub API 更新訂閱項目,並設定無法傳送訊息的主題。

控制台

如要更新訂閱項目並設定無法傳送訊息的主題,請完成下列步驟。

  1. 前往 Google Cloud 控制台的「Subscriptions」(訂閱項目) 頁面。

    前往「訂閱項目」頁面

  2. 找出要更新的訂閱項目,然後按一下旁邊的「更多動作」圖示

  3. 在內容選單中,選取「編輯」

    醒目顯示「編輯」選項的內容選單。

  4. 在「無效信件」部分,選取「啟用無效信件」

  5. 從下拉式選單中選擇無效信件主題。

    如果所選無效信件主題沒有訂閱項目,系統會提示您建立訂閱項目。

  6. 在「傳送嘗試次數上限」欄位中,指定介於 5 至 100 之間的整數。

  7. 按一下「Update」

  8. 按一下「詳細資料」面板,找出所有可能的動作項目。如果任何項目顯示錯誤圖示 ,請按一下動作項目來解決問題。

    「Dead Lettering」分頁,其中包含一些待辦事項。

gcloud

如要更新訂閱項目並設定無法傳送的訊息主題,請使用 gcloud pubsub subscriptions update 指令:

gcloud pubsub subscriptions update subscription-id \   --dead-letter-topic=dead-letter-topic-name \   [--max-delivery-attempts=max-delivery-attempts] \   [--dead-letter-topic-project=dead-letter-topic-project]

C++

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 C++ 設定操作說明進行操作。詳情請參閱 Pub/Sub C++ API 參考說明文件

namespace pubsub_admin = ::google::cloud::pubsub_admin; namespace pubsub = ::google::cloud::pubsub; [](pubsub_admin::SubscriptionAdminClient client,    std::string const& project_id, std::string const& subscription_id,    std::string const& dead_letter_topic_id,    int dead_letter_delivery_attempts) {   google::pubsub::v1::UpdateSubscriptionRequest request;   request.mutable_subscription()->set_name(       pubsub::Subscription(project_id, subscription_id).FullName());   request.mutable_subscription()       ->mutable_dead_letter_policy()       ->set_dead_letter_topic(           pubsub::Topic(project_id, dead_letter_topic_id).FullName());   request.mutable_subscription()       ->mutable_dead_letter_policy()       ->set_max_delivery_attempts(dead_letter_delivery_attempts);   *request.mutable_update_mask()->add_paths() = "dead_letter_policy";   auto sub = client.UpdateSubscription(request);   if (!sub) throw std::move(sub).status();    std::cout << "The subscription has been updated to: " << sub->DebugString()             << "\n";    std::cout << "It will forward dead letter messages to: "             << sub->dead_letter_policy().dead_letter_topic() << "\n";    std::cout << "After " << sub->dead_letter_policy().max_delivery_attempts()             << " delivery attempts.\n"; }

C#

在嘗試這個範例之前,請先按照快速入門:使用用戶端程式庫中的 C# 設定操作說明進行操作。詳情請參閱 Pub/Sub C# API 參考說明文件

 using Google.Cloud.PubSub.V1; using Google.Protobuf.WellKnownTypes;  public class UpdateDeadLetterPolicySample {     public Subscription UpdateDeadLetterPolicy(string projectId, string topicId, string subscriptionId, string deadLetterTopicId)     {         SubscriberServiceApiClient subscriber = SubscriberServiceApiClient.Create();         // This is an existing topic that the subscription with dead letter policy is attached to.         TopicName topicName = TopicName.FromProjectTopic(projectId, topicId);         // This is an existing subscription with a dead letter policy.         SubscriptionName subscriptionName = SubscriptionName.FromProjectSubscription(projectId, subscriptionId);         // This is an existing dead letter topic that the subscription with dead letter policy forwards         // dead letter messages to.         var deadLetterTopic = TopicName.FromProjectTopic(projectId, deadLetterTopicId).ToString();           // Construct the subscription with the dead letter policy you expect to have after the update.         // Here, values in the required fields (name, topic) help identify the subscription.         var subscription = new Subscription         {             SubscriptionName = subscriptionName,             TopicAsTopicName = topicName,             DeadLetterPolicy = new DeadLetterPolicy             {                 DeadLetterTopic = deadLetterTopic,                 MaxDeliveryAttempts = 20,             }         };          var request = new UpdateSubscriptionRequest         {             Subscription = subscription,             // Construct a field mask to indicate which field to update in the subscription.             UpdateMask = new FieldMask { Paths = { "dead_letter_policy" } }         };         var updatedSubscription = subscriber.UpdateSubscription(request);         return updatedSubscription;     } }

Go

以下範例使用 Go Pub/Sub 用戶端程式庫的主要版本 (v2)。如果您仍在使用第 1 版程式庫,請參閱第 2 版遷移指南。如要查看第 1 版程式碼範例清單,請參閱 已淘汰的程式碼範例

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的操作說明設定 Go 環境。詳情請參閱 Pub/Sub Go API 參考說明文件

import ( 	"context" 	"fmt" 	"io"  	"cloud.google.com/go/pubsub/v2" 	"cloud.google.com/go/pubsub/v2/apiv1/pubsubpb" 	"google.golang.org/protobuf/types/known/fieldmaskpb" )  // updateDeadLetter updates an existing subscription with a dead letter policy. func updateDeadLetter(w io.Writer, projectID, subscription, deadLetterTopic string) error { 	// projectID := "my-project-id" 	// subID := "projects/my-project-id/subscriptions/my-sub" 	// deadLetterTopic := "projects/my-project-id/topics/my-dead-letter-topic" 	ctx := context.Background() 	client, err := pubsub.NewClient(ctx, projectID) 	if err != nil { 		return fmt.Errorf("pubsub.NewClient: %w", err) 	} 	defer client.Close()  	sub, err := client.SubscriptionAdminClient.UpdateSubscription(ctx, &pubsubpb.UpdateSubscriptionRequest{ 		Subscription: &pubsubpb.Subscription{ 			Name: subscription, 			DeadLetterPolicy: &pubsubpb.DeadLetterPolicy{ 				MaxDeliveryAttempts: 20, 				DeadLetterTopic:     deadLetterTopic, 			}, 		}, 		UpdateMask: &fieldmaskpb.FieldMask{ 			Paths: []string{"dead_letter_policy"}, 		}, 	}) 	if err != nil { 		return fmt.Errorf("UpdateSubscription: %w", err) 	} 	fmt.Fprintf(w, "Updated subscription: %+v\n", sub) 	return nil } 

Java

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Java 設定操作說明進行操作。詳情請參閱 Pub/Sub Java API 參考說明文件

 import com.google.cloud.pubsub.v1.SubscriptionAdminClient; import com.google.protobuf.FieldMask; import com.google.pubsub.v1.DeadLetterPolicy; import com.google.pubsub.v1.Subscription; import com.google.pubsub.v1.SubscriptionName; import com.google.pubsub.v1.TopicName; import com.google.pubsub.v1.UpdateSubscriptionRequest; import java.io.IOException;  public class UpdateDeadLetterPolicyExample {   public static void main(String... args) throws Exception {     // TODO(developer): Replace these variables before running the sample.     String projectId = "your-project-id";     // This is an existing subscription with a dead letter policy.     String subscriptionId = "your-subscription-id";     // This is an existing topic that the subscription with dead letter policy is attached to.     String topicId = "your-topic-id";     // This is an existing dead letter topic that the subscription with dead letter policy forwards     // dead letter messages to.     String deadLetterTopicId = "your-dead-letter-topic-id";      UpdateDeadLetterPolicyExample.updateDeadLetterPolicyExample(         projectId, subscriptionId, topicId, deadLetterTopicId);   }    public static void updateDeadLetterPolicyExample(       String projectId, String subscriptionId, String topicId, String deadLetterTopicId)       throws IOException {     try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {        SubscriptionName subscriptionName = SubscriptionName.of(projectId, subscriptionId);        System.out.println(           "Before: " + subscriptionAdminClient.getSubscription(subscriptionName).getAllFields());        TopicName topicName = TopicName.of(projectId, topicId);       TopicName deadLetterTopicName = TopicName.of(projectId, deadLetterTopicId);        // Construct the dead letter policy you expect to have after the update.       DeadLetterPolicy deadLetterPolicy =           DeadLetterPolicy.newBuilder()               .setDeadLetterTopic(deadLetterTopicName.toString())               .setMaxDeliveryAttempts(20)               .build();        // Construct the subscription with the dead letter policy you expect to have       // after the update. Here, values in the required fields (name, topic) help       // identify the subscription.       Subscription subscription =           Subscription.newBuilder()               .setName(subscriptionName.toString())               .setTopic(topicName.toString())               .setDeadLetterPolicy(deadLetterPolicy)               .build();        // Construct a field mask to indicate which field to update in the subscription.       FieldMask updateMask =           FieldMask.newBuilder().addPaths("dead_letter_policy.max_delivery_attempts").build();        UpdateSubscriptionRequest request =           UpdateSubscriptionRequest.newBuilder()               .setSubscription(subscription)               .setUpdateMask(updateMask)               .build();        Subscription response = subscriptionAdminClient.updateSubscription(request);        System.out.println("After: " + response.getAllFields());       System.out.println(           "Max delivery attempts is now "               + response.getDeadLetterPolicy().getMaxDeliveryAttempts());     }   } }

Node.js

在嘗試這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Node.js 設定說明進行操作。詳情請參閱 Pub/Sub Node.js API 參考說明文件

/**  * TODO(developer): Uncomment these variables before running the sample.  */ // const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID'; // const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';  // Imports the Google Cloud client library const {PubSub} = require('@google-cloud/pubsub');  // Creates a client; cache this for further use const pubSubClient = new PubSub();  async function updateDeadLetterPolicy(topicNameOrId, subscriptionNameOrId) {   const metadata = {     deadLetterPolicy: {       deadLetterTopic: pubSubClient.topic(topicNameOrId).name,       maxDeliveryAttempts: 15,     },   };    await pubSubClient     .topic(topicNameOrId)     .subscription(subscriptionNameOrId)     .setMetadata(metadata);    console.log('Max delivery attempts updated successfully.'); }

PHP

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 PHP 設定說明進行操作。 詳情請參閱 Pub/Sub PHP API 參考說明文件

use Google\Cloud\PubSub\PubSubClient;  /**  * Set the dead letter policy on an existing subscription.  *  * @param string $projectId  The Google project ID.  * @param string $topicName  The Pub/Sub topic name.  * @param string $deadLetterTopicName The Pub/Sub topic to use for dead letter policy.  */ function dead_letter_update_subscription(     string $projectId,     string $topicName,     string $subscriptionName,     string $deadLetterTopicName ): void {     $pubsub = new PubSubClient([         'projectId' => $projectId,     ]);      $topic = $pubsub->topic($topicName);     $deadLetterTopic = $pubsub->topic($deadLetterTopicName);      $subscription = $topic->subscription($subscriptionName);     $subscription->update([         'deadLetterPolicy' => [             'deadLetterTopic' => $deadLetterTopic         ]     ]);      printf(         'Subscription %s updated with dead letter topic %s' . PHP_EOL,         $subscription->name(),         $deadLetterTopic->name()     ); }

Python

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Python 設定操作說明來進行。詳情請參閱 Pub/Sub Python API 參考說明文件

from google.cloud import pubsub_v1 from google.cloud.pubsub_v1.types import DeadLetterPolicy, FieldMask  # TODO(developer) # project_id = "your-project-id" # TODO(developer): This is an existing topic that the subscription # with dead letter policy is attached to. # topic_id = "your-topic-id" # TODO(developer): This is an existing subscription with a dead letter policy. # subscription_id = "your-subscription-id" # TODO(developer): This is an existing dead letter topic that the subscription # with dead letter policy will forward dead letter messages to. # dead_letter_topic_id = "your-dead-letter-topic-id" # TODO(developer): This is the maximum number of delivery attempts allowed # for a message before it gets delivered to a dead letter topic. # max_delivery_attempts = 5  publisher = pubsub_v1.PublisherClient() subscriber = pubsub_v1.SubscriberClient()  topic_path = publisher.topic_path(project_id, topic_id) subscription_path = subscriber.subscription_path(project_id, subscription_id) dead_letter_topic_path = publisher.topic_path(project_id, dead_letter_topic_id)  subscription_before_update = subscriber.get_subscription(     request={"subscription": subscription_path} ) print(f"Before the update: {subscription_before_update}.")  # Indicates which fields in the provided subscription to update. update_mask = FieldMask(paths=["dead_letter_policy"])  # Construct a dead letter policy you expect to have after the update. dead_letter_policy = DeadLetterPolicy(     dead_letter_topic=dead_letter_topic_path,     max_delivery_attempts=max_delivery_attempts, )  # Construct the subscription with the dead letter policy you expect to have # after the update. Here, values in the required fields (name, topic) help # identify the subscription. subscription = pubsub_v1.types.Subscription(     name=subscription_path,     topic=topic_path,     dead_letter_policy=dead_letter_policy, )  with subscriber:     subscription_after_update: gapic_types.Subscription = (         subscriber.update_subscription(             request={"subscription": subscription, "update_mask": update_mask}         )     )  print(f"After the update: {subscription_after_update}.")

Ruby

以下範例使用 Ruby Pub/Sub 用戶端程式庫 v3。如果您仍在使用第 2 版程式庫,請參閱 第 3 版遷移指南。如要查看 Ruby 第 2 版程式碼範例清單,請參閱 已淘汰的程式碼範例

在試用這個範例之前,請先按照「快速入門:使用用戶端程式庫」的操作說明設定 Ruby 環境。詳情請參閱 Pub/Sub Ruby API 參考說明文件

Ruby

在試用這個範例之前,請先按照RubyPub/Sub 快速入門導覽課程:使用用戶端程式庫」中的操作說明進行設定。 詳情請參閱 Pub/Sub Ruby API 參考說明文件

如要驗證 Pub/Sub,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

# subscription_id       = "your-subscription-id" # role                  = "roles/pubsub.publisher" # service_account_email = # "serviceAccount:account_name@project_name.iam.gserviceaccount.com"  pubsub = Google::Cloud::PubSub.new subscription_admin = pubsub.subscription_admin  subscription = subscription_admin.get_subscription \   subscription: pubsub.subscription_path(subscription_id) subscription.dead_letter_policy.max_delivery_attempts = 20  subscription_admin.update_subscription subscription: subscription,                                        update_mask: {                                          paths: ["dead_letter_policy"]                                        }  puts "Max delivery attempts is now " \      "#{subscription.dead_letter_policy.max_delivery_attempts}."

授予使用無效信件主題的 IAM 角色

如要將無法傳送的訊息轉送至無效信件主題,Pub/Sub 必須具備下列權限:

  • 將訊息發布至主題。
  • 確認訊息,將訊息從訂閱項目中移除。

Pub/Sub 會為每個專案建立及維護服務帳戶: service-project-number@gcp-sa-pubsub.iam.gserviceaccount.com。 您可以將發布者和訂閱者角色指派給這個服務帳戶,藉此授予轉送權限。

控制台

如要授予 Pub/Sub 權限,將訊息發布至死信主題,請完成下列步驟:

  1. 前往 Google Cloud 控制台的「Subscriptions」(訂閱項目) 頁面。

    前往「訂閱項目」頁面

  2. 按一下具有無法傳送訊息主題的訂閱項目名稱。

  3. 按一下「Dead lettering」(無法投遞的郵件) 分頁標籤。

  4. 如要指派發布者角色,請按一下「授予發布者角色」。如果已成功指派發布者角色,就會看到藍色勾號

  5. 如要指派訂閱者角色,請按一下「授予訂閱者角色」。如果已成功指派發布者角色,就會看到藍色勾號

gcloud

如要授予 Pub/Sub 權限,將訊息發布至死信主題,請執行下列指令:

PUBSUB_SERVICE_ACCOUNT="service-project-number@gcp-sa-pubsub.iam.gserviceaccount.com"  gcloud pubsub topics add-iam-policy-binding dead-letter-topic-name \   --member="serviceAccount:$PUBSUB_SERVICE_ACCOUNT"\   --role="roles/pubsub.publisher"

如要授予 Pub/Sub 權限,確認轉送的無法傳送訊息,請執行下列指令:

PUBSUB_SERVICE_ACCOUNT="service-project-number@gcp-sa-pubsub.iam.gserviceaccount.com"  gcloud pubsub subscriptions add-iam-policy-binding subscription-id \   --member="serviceAccount:$PUBSUB_SERVICE_ACCOUNT"\   --role="roles/pubsub.subscriber"

追蹤投遞嘗試

為訂閱項目啟用無效信件主題後,該訂閱項目的每則訊息都會有一個欄位,用於指定傳送嘗試次數:

  • 從提取訂閱項目收到的訊息會包含 delivery_attempt 欄位。

  • 從推送訂閱項目收到的訊息會包含 deliveryAttempt 欄位。

下列範例說明如何取得嘗試遞送次數:

C++

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 C++ 設定操作說明進行操作。詳情請參閱 Pub/Sub C++ API 參考說明文件

namespace pubsub = ::google::cloud::pubsub; auto sample = [](pubsub::Subscriber subscriber) {   return subscriber.Subscribe(       [&](pubsub::Message const& m, pubsub::AckHandler h) {         std::cout << "Received message " << m << "\n";         std::cout << "Delivery attempt: " << h.delivery_attempt() << "\n";         std::move(h).ack();         PleaseIgnoreThisSimplifiesTestingTheSamples();       }); };

C#

在嘗試這個範例之前,請先按照快速入門:使用用戶端程式庫中的 C# 設定操作說明進行操作。詳情請參閱 Pub/Sub C# API 參考說明文件

 using Google.Cloud.PubSub.V1; using System.Threading; using System.Threading.Tasks;  public class PullMessagesAsyncWithDeliveryAttemptsSample {     public async Task<int> PullMessagesAsyncWithDeliveryAttempts(string projectId, string subscriptionId, bool acknowledge)     {         // This is an existing subscription with a dead letter policy.         SubscriptionName subscriptionName = SubscriptionName.FromProjectSubscription(projectId, subscriptionId);          SubscriberClient subscriber = await SubscriberClient.CreateAsync(subscriptionName);          int deliveryAttempt = 0;         Task startTask = subscriber.StartAsync((PubsubMessage message, CancellationToken cancel) =>         {             string text = message.Data.ToStringUtf8();             System.Console.WriteLine($"Delivery Attempt: {message.GetDeliveryAttempt()}");             if (message.GetDeliveryAttempt() != null)             {                 deliveryAttempt = message.GetDeliveryAttempt().Value;             }             return Task.FromResult(acknowledge ? SubscriberClient.Reply.Ack : SubscriberClient.Reply.Nack);         });         // Run for 7 seconds.         await Task.Delay(7000);         await subscriber.StopAsync(CancellationToken.None);         // Lets make sure that the start task finished successfully after the call to stop.         await startTask;         return deliveryAttempt;     } }

Go

以下範例使用 Go Pub/Sub 用戶端程式庫的主要版本 (v2)。如果您仍在使用第 1 版程式庫,請參閱第 2 版遷移指南。如要查看第 1 版程式碼範例清單,請參閱 已淘汰的程式碼範例

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的操作說明設定 Go 環境。詳情請參閱 Pub/Sub Go API 參考說明文件

import ( 	"context" 	"fmt" 	"io" 	"time"  	"cloud.google.com/go/pubsub/v2" )  func pullMsgsDeadLetterDeliveryAttempt(w io.Writer, projectID, subID string) error { 	// projectID := "my-project-id" 	// subID := "my-sub" 	ctx := context.Background() 	client, err := pubsub.NewClient(ctx, projectID) 	if err != nil { 		return fmt.Errorf("pubsub.NewClient: %w", err) 	} 	defer client.Close()  	// Receive messages for 10 seconds, which simplifies testing. 	// Comment this out in production, since `Receive` should 	// be used as a long running operation. 	ctx, cancel := context.WithTimeout(ctx, 10*time.Second) 	defer cancel()  	// client.Subscriber can be passed a subscription ID (e.g. "my-sub") or 	// a fully qualified name (e.g. "projects/my-project/subscriptions/my-sub"). 	// If a subscription ID is provided, the project ID from the client is used. 	sub := client.Subscriber(subID) 	err = sub.Receive(ctx, func(_ context.Context, msg *pubsub.Message) { 		// When dead lettering is enabled, the delivery attempt field is a pointer to the 		// the number of times the service has attempted to delivery a message. 		// Otherwise, the field is nil. 		if msg.DeliveryAttempt != nil { 			fmt.Fprintf(w, "message: %s, delivery attempts: %d", msg.Data, *msg.DeliveryAttempt) 		} 		msg.Ack() 	}) 	if err != nil { 		return fmt.Errorf("got error in Receive: %w", err) 	} 	return nil } 

Java

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Java 設定操作說明進行操作。詳情請參閱 Pub/Sub Java API 參考說明文件

 import com.google.cloud.pubsub.v1.AckReplyConsumer; import com.google.cloud.pubsub.v1.MessageReceiver; import com.google.cloud.pubsub.v1.Subscriber; import com.google.pubsub.v1.ProjectSubscriptionName; import com.google.pubsub.v1.PubsubMessage; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException;  public class ReceiveMessagesWithDeliveryAttemptsExample {    public static void main(String... args) throws Exception {     // TODO(developer): Replace these variables before running the sample.     String projectId = "your-project-id";     // This is an existing subscription with a dead letter policy.     String subscriptionId = "your-subscription-id";      ReceiveMessagesWithDeliveryAttemptsExample.receiveMessagesWithDeliveryAttemptsExample(         projectId, subscriptionId);   }    public static void receiveMessagesWithDeliveryAttemptsExample(       String projectId, String subscriptionId) {      ProjectSubscriptionName subscriptionName =         ProjectSubscriptionName.of(projectId, subscriptionId);      // Instantiate an asynchronous message receiver.     MessageReceiver receiver =         new MessageReceiver() {           @Override           public void receiveMessage(PubsubMessage message, AckReplyConsumer consumer) {             // Handle incoming message, then ack the received message.             System.out.println("Id: " + message.getMessageId());             System.out.println("Data: " + message.getData().toStringUtf8());             System.out.println("Delivery Attempt: " + Subscriber.getDeliveryAttempt(message));             consumer.ack();           }         };      Subscriber subscriber = null;     try {       subscriber = Subscriber.newBuilder(subscriptionName, receiver).build();       // Start the subscriber.       subscriber.startAsync().awaitRunning();       System.out.printf("Listening for messages on %s:\n", subscriptionName.toString());       // Allow the subscriber to run for 30s unless an unrecoverable error occurs.       subscriber.awaitTerminated(30, TimeUnit.SECONDS);     } catch (TimeoutException timeoutException) {       // Shut down the subscriber after 30s. Stop receiving messages.       subscriber.stopAsync();     }   } }

Node.js

在嘗試這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Node.js 設定說明進行操作。詳情請參閱 Pub/Sub Node.js API 參考說明文件

/**  * TODO(developer): Uncomment these variables before running the sample.  */ // const projectId = 'YOUR_PROJECT_ID'; // const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';  // Imports the Google Cloud client library. v1 is for the lower level // proto access. const {v1} = require('@google-cloud/pubsub');  // Creates a client; cache this for further use. const subClient = new v1.SubscriberClient();  async function synchronousPullWithDeliveryAttempts(   projectId,   subscriptionNameOrId, ) {   // The low level API client requires a name only.   const formattedSubscription =     subscriptionNameOrId.indexOf('/') >= 0       ? subscriptionNameOrId       : subClient.subscriptionPath(projectId, subscriptionNameOrId);    // The maximum number of messages returned for this request.   // Pub/Sub may return fewer than the number specified.   const request = {     subscription: formattedSubscription,     maxMessages: 10,   };    // The subscriber pulls a specified number of messages.   const [response] = await subClient.pull(request);    // Process the messages.   const ackIds = [];   for (const message of response.receivedMessages || []) {     console.log(`Received message: ${message.message.data}`);     console.log(`Delivery Attempt: ${message.deliveryAttempt}`);     if (message.ackId) {       ackIds.push(message.ackId);     }   }    // Acknowledge all of the messages. You could also acknowledge   // these individually, but this is more efficient.   const ackRequest = {     subscription: formattedSubscription,     ackIds: ackIds,   };   await subClient.acknowledge(ackRequest);    console.log('Done.'); }

PHP

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 PHP 設定說明進行操作。 詳情請參閱 Pub/Sub PHP API 參考說明文件

use Google\Cloud\PubSub\Message; use Google\Cloud\PubSub\PubSubClient;  /**  * Get the delivery attempt from a pulled message.  *  * @param string $projectId  The Google project ID.  * @param string $topicName  The Pub/Sub topic name.  * @param string $subscriptionName  The Pub/Sub subscription name.  * @param string $message The contents of a pubsub message data field.  */ function dead_letter_delivery_attempt($projectId, $topicName, $subscriptionName, $message) {     $pubsub = new PubSubClient([         'projectId' => $projectId,     ]);      $topic = $pubsub->topic($topicName);      // publish test message     $topic->publish(new Message([         'data' => $message     ]));      $subscription = $topic->subscription($subscriptionName);     $messages = $subscription->pull();      foreach ($messages as $message) {         printf('Received message %s' . PHP_EOL, $message->data());         printf('Delivery attempt %d' . PHP_EOL, $message->deliveryAttempt());     }     print('Done' . PHP_EOL); }

Python

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Python 設定操作說明來進行。詳情請參閱 Pub/Sub Python API 參考說明文件

from concurrent.futures import TimeoutError from google.cloud import pubsub_v1  # TODO(developer) # project_id = "your-project-id" # subscription_id = "your-subscription-id"  subscriber = pubsub_v1.SubscriberClient() subscription_path = subscriber.subscription_path(project_id, subscription_id)  def callback(message: pubsub_v1.subscriber.message.Message) -> None:     print(f"Received {message}.")     print(f"With delivery attempts: {message.delivery_attempt}.")     message.ack()  streaming_pull_future = subscriber.subscribe(subscription_path, callback=callback) print(f"Listening for messages on {subscription_path}..\n")  # Wrap subscriber in a 'with' block to automatically call close() when done. with subscriber:     # When `timeout` is not set, result() will block indefinitely,     # unless an exception is encountered first.     try:         streaming_pull_future.result(timeout=timeout)     except TimeoutError:         streaming_pull_future.cancel()  # Trigger the shutdown.         streaming_pull_future.result()  # Block until the shutdown is complete.

Ruby

以下範例使用 Ruby Pub/Sub 用戶端程式庫 v3。如果您仍在使用第 2 版程式庫,請參閱 第 3 版遷移指南。如要查看 Ruby 第 2 版程式碼範例清單,請參閱 已淘汰的程式碼範例

在試用這個範例之前,請先按照「快速入門:使用用戶端程式庫」的操作說明設定 Ruby 環境。詳情請參閱 Pub/Sub Ruby API 參考說明文件

# subscription_id = "your-subscription-id"  pubsub = Google::Cloud::PubSub.new subscriber = pubsub.subscriber subscription_id  subscriber.pull(immediate: false).each do |message|   puts "Received message: #{message.data}"   puts "Delivery Attempt: #{message.delivery_attempt}"   message.acknowledge! end

當 Pub/Sub 將無法傳送的訊息轉送至無效信件主題時,會為訊息新增下列屬性

  • CloudPubSubDeadLetterSourceDeliveryCount:傳送至來源訂閱項目的嘗試次數。
  • CloudPubSubDeadLetterSourceSubscription:來源訂閱項目的名稱。
  • CloudPubSubDeadLetterSourceSubscriptionProject:包含來源訂閱項目的專案名稱。
  • CloudPubSubDeadLetterSourceTopicPublishTime:訊息最初發布的時間戳記。
  • CloudPubSubDeadLetterSourceDeliveryErrorMessage:郵件無法傳送至原始目的地的原因。這項屬性僅適用於匯出訂閱項目

監控轉寄的郵件

轉送無法傳送的訊息後,Pub/Sub 服務會從訂閱項目中移除該訊息。您可以使用 Cloud Monitoring 監控轉寄的訊息。

如果將訂閱項目附加至無效信件主題,訊息會使用附加訂閱項目的到期政策,而不是具有無效信件主題屬性的訂閱項目到期時間。

subscription/dead_letter_message_count 指標會記錄 Pub/Sub 從訂閱項目轉送的無法遞送訊息數量。

詳情請參閱「監控轉寄的無法傳送郵件」。

移除無效信件主題

如要停止轉寄無法傳送的訊息,請從訂閱項目中移除無效信件主題。

您可以使用Google Cloud 控制台、gcloud CLI 或 Pub/Sub API,從訂閱項目中移除無法傳送訊息的主題。

控制台

如要從訂閱項目中移除死信主題,請完成下列步驟:

  1. 前往 Google Cloud 控制台的「Subscriptions」(訂閱項目) 頁面。

    前往「訂閱項目」頁面

  2. 在訂閱項目清單中,按一下要更新的訂閱項目旁邊的

  3. 在內容選單中,選取「編輯」

    醒目顯示「編輯」選項的內容選單。

  4. 在「無效信件」專區中,清除「啟用無效信件」核取方塊。

  5. 按一下「Update」

gcloud

如要從訂閱項目移除無法傳送訊息的主題,請使用 gcloud pubsub subscriptions update 指令和 --clear-dead-letter-policy 標記:

gcloud pubsub subscriptions update subscription-id \   --clear-dead-letter-policy

C++

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 C++ 設定操作說明進行操作。詳情請參閱 Pub/Sub C++ API 參考說明文件

namespace pubsub_admin = ::google::cloud::pubsub_admin; namespace pubsub = ::google::cloud::pubsub; [](pubsub_admin::SubscriptionAdminClient client,    std::string const& project_id, std::string const& subscription_id) {   google::pubsub::v1::UpdateSubscriptionRequest request;   request.mutable_subscription()->set_name(       pubsub::Subscription(project_id, subscription_id).FullName());   request.mutable_subscription()->clear_dead_letter_policy();   *request.mutable_update_mask()->add_paths() = "dead_letter_policy";   auto sub = client.UpdateSubscription(request);   if (!sub) throw std::move(sub).status();    std::cout << "The subscription has been updated to: " << sub->DebugString()             << "\n"; }

C#

在嘗試這個範例之前,請先按照快速入門:使用用戶端程式庫中的 C# 設定操作說明進行操作。詳情請參閱 Pub/Sub C# API 參考說明文件

 using Google.Cloud.PubSub.V1; using Google.Protobuf.WellKnownTypes;  public class RemoveDeadLetterPolicySample {     public Subscription RemoveDeadLetterPolicy(string projectId, string topicId, string subscriptionId)     {         SubscriberServiceApiClient subscriber = SubscriberServiceApiClient.Create();         // This is an existing topic that the subscription with dead letter policy is attached to.         TopicName topicName = TopicName.FromProjectTopic(projectId, topicId);         // This is an existing subscription with dead letter policy.         SubscriptionName subscriptionName = SubscriptionName.FromProjectSubscription(projectId, subscriptionId);          var subscription = new Subscription()         {             SubscriptionName = subscriptionName,             TopicAsTopicName = topicName,             DeadLetterPolicy = null         };          var request = new UpdateSubscriptionRequest         {             Subscription = subscription,             UpdateMask = new FieldMask { Paths = { "dead_letter_policy" } }         };         var updatedSubscription = subscriber.UpdateSubscription(request);         return updatedSubscription;     } }

Go

以下範例使用 Go Pub/Sub 用戶端程式庫的主要版本 (v2)。如果您仍在使用第 1 版程式庫,請參閱第 2 版遷移指南。如要查看第 1 版程式碼範例清單,請參閱 已淘汰的程式碼範例

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的操作說明設定 Go 環境。詳情請參閱 Pub/Sub Go API 參考說明文件

import ( 	"context" 	"fmt" 	"io"  	"cloud.google.com/go/pubsub/v2" 	"cloud.google.com/go/pubsub/v2/apiv1/pubsubpb" 	"google.golang.org/protobuf/types/known/fieldmaskpb" )  // removeDeadLetterTopic removes the dead letter policy from a subscription. func removeDeadLetterTopic(w io.Writer, projectID, subscriptionName string) error { 	// projectID := "my-project-id" 	// subscription := "projects/my-project/subscriptions/my-sub" 	ctx := context.Background() 	client, err := pubsub.NewClient(ctx, projectID) 	if err != nil { 		return fmt.Errorf("pubsub.NewClient: %w", err) 	} 	defer client.Close()  	sub, err := client.SubscriptionAdminClient.UpdateSubscription(ctx, &pubsubpb.UpdateSubscriptionRequest{ 		Subscription: &pubsubpb.Subscription{ 			Name:             subscriptionName, 			DeadLetterPolicy: nil, // alternatively, you can omit this line entirely. 		}, 		UpdateMask: &fieldmaskpb.FieldMask{ 			Paths: []string{"dead_letter_policy"}, 		}, 	}) 	if err != nil { 		return fmt.Errorf("UpdateSubscription: %w", err) 	} 	fmt.Fprintf(w, "Updated subscription: %+v\n", sub) 	return nil } 

Java

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Java 設定操作說明進行操作。詳情請參閱 Pub/Sub Java API 參考說明文件

 import com.google.cloud.pubsub.v1.SubscriptionAdminClient; import com.google.protobuf.FieldMask; import com.google.pubsub.v1.ProjectSubscriptionName; import com.google.pubsub.v1.Subscription; import com.google.pubsub.v1.TopicName; import com.google.pubsub.v1.UpdateSubscriptionRequest;  public class RemoveDeadLetterPolicyExample {    public static void main(String... args) throws Exception {     // TODO(developer): Replace these variables before running the sample.     String projectId = "your-project-id";     // This is an existing subscription with dead letter policy.     String subscriptionId = "your-subscription-id";     // This is an existing topic that the subscription with dead letter policy is attached to.     String topicId = "your-topic-id";      RemoveDeadLetterPolicyExample.removeDeadLetterPolicyExample(projectId, subscriptionId, topicId);   }    public static void removeDeadLetterPolicyExample(       String projectId, String subscriptionId, String topicId) throws Exception {     try (SubscriptionAdminClient subscriptionAdminClient = SubscriptionAdminClient.create()) {        ProjectSubscriptionName subscriptionName =           ProjectSubscriptionName.of(projectId, subscriptionId);       TopicName topicName = TopicName.of(projectId, topicId);        // Construct the subscription you expect to have after the request. Here,       // values in the required fields (name, topic) help identify the subscription.       // No dead letter policy is supplied.       Subscription expectedSubscription =           Subscription.newBuilder()               .setName(subscriptionName.toString())               .setTopic(topicName.toString())               .build();        // Construct a field mask to indicate which field to update in the subscription.       FieldMask updateMask = FieldMask.newBuilder().addPaths("dead_letter_policy").build();        UpdateSubscriptionRequest request =           UpdateSubscriptionRequest.newBuilder()               .setSubscription(expectedSubscription)               .setUpdateMask(updateMask)               .build();        Subscription response = subscriptionAdminClient.updateSubscription(request);        // You should see an empty dead letter topic field inside the dead letter policy.       System.out.println("After: " + response.getAllFields());     }   } }

Node.js

在嘗試這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Node.js 設定說明進行操作。詳情請參閱 Pub/Sub Node.js API 參考說明文件

/**  * TODO(developer): Uncomment these variables before running the sample.  */ // const topicNameOrId = 'YOUR_TOPIC_NAME_OR_ID'; // const subscriptionNameOrId = 'YOUR_SUBSCRIPTION_NAME_OR_ID';  // Imports the Google Cloud client library const {PubSub} = require('@google-cloud/pubsub');  // Creates a client; cache this for further use const pubSubClient = new PubSub();  async function removeDeadLetterPolicy(topicNameOrId, subscriptionNameOrId) {   const metadata = {     deadLetterPolicy: null,   };    await pubSubClient     .topic(topicNameOrId)     .subscription(subscriptionNameOrId)     .setMetadata(metadata);    console.log(     `Removed dead letter topic from ${subscriptionNameOrId} subscription.`,   ); }

PHP

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 PHP 設定說明進行操作。 詳情請參閱 Pub/Sub PHP API 參考說明文件

use Google\Cloud\PubSub\PubSubClient;  /**  * Remove dead letter policy from an existing subscription.  *  * @param string $projectId  The Google project ID.  * @param string $topicName  The Pub/Sub topic name.  * @param string $subscriptionName  The Pub/Sub subscription name.  */ function dead_letter_remove($projectId, $topicName, $subscriptionName) {     $pubsub = new PubSubClient([         'projectId' => $projectId,     ]);      $topic = $pubsub->topic($topicName);      $subscription = $topic->subscription($subscriptionName);      // Provide deadLetterPolicy in the update mask, but omit from update fields to unset.     $subscription->update([], [         'updateMask' => [             'deadLetterPolicy'         ]     ]);      printf(         'Removed dead letter topic from subscription %s' . PHP_EOL,         $subscription->name()     ); }

Python

在試用這個範例之前,請先按照快速入門:使用用戶端程式庫中的 Python 設定操作說明來進行。詳情請參閱 Pub/Sub Python API 參考說明文件

from google.cloud import pubsub_v1 from google.cloud.pubsub_v1.types import FieldMask  # TODO(developer) # project_id = "your-project-id" # TODO(developer): This is an existing topic that the subscription # with dead letter policy is attached to. # topic_id = "your-topic-id" # TODO(developer): This is an existing subscription with a dead letter policy. # subscription_id = "your-subscription-id"  publisher = pubsub_v1.PublisherClient() subscriber = pubsub_v1.SubscriberClient() topic_path = publisher.topic_path(project_id, topic_id) subscription_path = subscriber.subscription_path(project_id, subscription_id)  subscription_before_update = subscriber.get_subscription(     request={"subscription": subscription_path} ) print(f"Before removing the policy: {subscription_before_update}.")  # Indicates which fields in the provided subscription to update. update_mask = FieldMask(paths=["dead_letter_policy"])  # Construct the subscription (without any dead letter policy) that you # expect to have after the update. subscription = pubsub_v1.types.Subscription(     name=subscription_path, topic=topic_path )  with subscriber:     subscription_after_update: gapic_types.Subscription = (         subscriber.update_subscription(             request={"subscription": subscription, "update_mask": update_mask}         )     )  print(f"After removing the policy: {subscription_after_update}.")

Ruby

以下範例使用 Ruby Pub/Sub 用戶端程式庫 v3。如果您仍在使用第 2 版程式庫,請參閱 第 3 版遷移指南。如要查看 Ruby 第 2 版程式碼範例清單,請參閱 已淘汰的程式碼範例

在試用這個範例之前,請先按照「快速入門:使用用戶端程式庫」的操作說明設定 Ruby 環境。詳情請參閱 Pub/Sub Ruby API 參考說明文件

Ruby

在試用這個範例之前,請先按照RubyPub/Sub 快速入門導覽課程:使用用戶端程式庫」中的操作說明進行設定。 詳情請參閱 Pub/Sub Ruby API 參考說明文件

如要驗證 Pub/Sub,請設定應用程式預設憑證。 詳情請參閱「為本機開發環境設定驗證」。

# subscription_id = "your-subscription-id"  pubsub = Google::Cloud::PubSub.new subscription_admin = pubsub.subscription_admin  subscription = subscription_admin.get_subscription \   subscription: pubsub.subscription_path(subscription_id) subscription.dead_letter_policy = nil  subscription_admin.update_subscription subscription: subscription,                                        update_mask: {                                          paths: ["dead_letter_policy"]                                        }  puts "Removed dead letter topic from #{subscription_id} subscription."

定價

如果 Pub/Sub 服務轉送無法傳送的訊息,則適用下列費用:

  • 發布費用會計入與含有死信主題的專案相關聯的帳單帳戶。
  • 系統會向與專案相關聯的帳單帳戶收取外送訊息的訂閱費用,而專案包含具有死信主題屬性的訂閱項目。

如果您為訂閱項目設定 dead-letter 主題屬性,但 dead-letter 主題的訊息儲存位置政策不允許包含訂閱項目的區域,系統也會收取輸出訊息的發布費用。

外寄訊息的發布費用會計入包含死信主題的專案。詳情請參閱「定價」。

## 後續步驟