Things I wish I knew about Pub/Sub, Part 3

Tianzi Cai
Google Cloud - Community
6 min readDec 18, 2020

--

In Part 1 and 2, my colleagues Megan and Alex introduced you to the Pub/Sub service and its official client libraries. In this last section, I will cover some remaining topics including push subscriptions, the emulator, IAM policies, and health metrics.

What is a push subscription and when do I use it?

Push subscriptions allow Pub/Sub to come to you: Pub/Sub delivers messages to a predefined HTTPS address (also called a push endpoint) as a HTTP POST request.

Unlike a pull subscription, where you actively ask Pub/Sub for messages, a push subscription lets you configure a push endpoint, and Pub/Sub delivers messages to this push endpoint.

You should consider a push subscription if any of the following applies:

  • You are not able to include any client library code in your subscriber application.
  • Your subscriber is not allowed to make any outgoing requests.
  • Your subscriber shall handle messages from different subscriptions the same way, i.e. you use the same push endpoint for different subscriptions.

Message acknowledgement in push subscriptions is achieved differently from that in pull subscriptions. In pull, your application code must explicitly call the acknowledge (ack) method on a received message. In push, a successful response code (one of 101, 200, 201, 202, 204) for a push request serves as an ack.

When a push request gets other response codes, indicating that the request has failed, a message is considered nack’ed, and the following will happen:

  • Pub/Sub will try to re-deliver the message with exponential backoff. This means you should expect longer periods between subsequent deliveries.
  • Pub/Sub will also lower the limit of outstanding messages, i.e. messages that Pub/Sub has sent out but have yet been ack’ed or nack’ed.

These measures aim at reducing the rate and volume of messages to your endpoint so it has a chance to recover. Detailed explanation on these calculations is in the official documentation.

Both pull and push subscriptions meet high-throughput needs. But the maximum throughput per subscription per region for the push mode of delivery is half of that of the pull-delivery mode per subscription per region. To learn the exact quote units, check out the reference page for quota limits.

How do I test the service?

A good way to test your code without incurring any cost is to use the Pub/Sub emulator, which has most of the basic functionalities, with some known limitations.

With the cloud SDK installed and initialized, you can start the emulator with the following command:

gcloud beta emulators pubsub start \
--project=abc \
--host-port=localhost:8085

This command starts the emulator on your localhost port 8085 — this is also the default if you don’t specify a value. If you do not supply a dummy project ID using the --project flag, the emulator will use the project that you have initialized with gcloud. From there, you shall set the environment variable PUBSUB_EMULATOR_HOST to localhost:8085, and you are good to start interacting with the emulated Pub/Sub service using the official client libraries.

Every time you start the emulator, you start with a blank slate. You shouldn’t expect any existing topics or subscriptions. Topics or subscriptions created during a session also disappear when you restart the emulator.

If you need to run the emulator inside a container for integrated testing or other reasons, you should update the emulator’s host in the --host-port flag to 0.0.0.0 instead of using the default localhost. This binds the port that the emulator is running on to all IP addresses in the container’s network namespace. No matter what the external IP address of the container is, the emulator will always be accessible on the specified port.

The following command starts a Pub/Sub emulator inside a Docker container on port 8085, and it exposes the container port 8085 to port 8080 on the Docker host.

docker run --rm -ti -p 8080:8085 \
gcr.io/google.com/cloudsdktool/cloud-sdk:$VERSION-emulators \
gcloud beta emulators pubsub start \
--project=abc \
--host-port=0.0.0.0:8085

Replace $VERSION with the version number of the most recent Google Cloud SDK image tagged with <version>-emulators in GCP’s public container registry.

After you have started the emulator, you can set PUBSUB_EMULATOR_HOST to localhost:8080 in your local development environment test your code using the emulator running in the Docker container. The Python example below creates a topic my-topic first and then list topics in the dummy project abc.

git clone https://github.com/googleapis/python-pubsub
cd python-pubsub/samples/snippets/
export PUBSUB_EMULATOR_HOST=localhost:8080
python publisher.py abc create my-topic
python publisehr.py abc list

Although the example for using the emulator on cloud.google.com is in Python, all language client libraries support using the emulator. As for the emulator’s feature parity with the real Pub/Sub service, I recommend checking back on its known limitations from time to time, as new features get added.

How do I configure IAM on my topic or subscription?

Fine grained access control can be achieved by setting roles and permissions at the topic and subscription level.

There may be times that you want to limit what a user or a third party service can do with your Pub/Sub resources.

For example, a downstream message consumer identified by a certain service account, perhaps from a different GCP project, should only have permissions to subscribe but not to update a subscription’s message retention policy. This can be achieved by setting the IAM policy on that subscription such that its policy member, the service account in this case, does not have a role with the pubsub.subscription.update permission. An example of a role with this permission is roles/pubsub.editor. An example of a role without this permission is roles/pubsub.subscriber.

Setting the IAM policy on a topic or subscription often involves three steps:

  • Getting the existing IAM policy for a topic or a subscription in a JSON or YAML file.
  • Updating the JSON or YAML file with changes you would like to make: add/remove a member, add/remove a role
  • Applying the changes in the JSON or YAML file to your topic or subscription.

Here is a summary of the predefined roles that you can add to a topic or subscription’s IAM policy. If you need to, you can also customize roles by mixing and matching permissions. (Also see GCP IAM roles explained.)

How do I check the health of my application?

Pub/Sub error codes allow you to diagnose your issues during development. Metrics allow you to check on the health of your topics and subscriptions.

Some commonly seen errors among new users are authentication errors like UNAUTHENTICATED and PERMISSION_DENIED. These are typically caused by setting the environment variable GOOGLE_APPLICATION_CREDENTIALS to a non-existent or wrong service account key file, causing the service to not know the identity carried by your requests or perceive it to lack proper permissions.

NOT_FOUND and ALREADY_EXISTS occur when you use a topic or subscription that has not been created, or you try to create a topic or subscription that has already been created.

As for the most common metrics, Cloud Console for Pub/Sub lets you view and set up alerts for publish requests and publish operations for your topics, as well as unacked message count and oldest message age for your subscriptions.

Publish requests refer to publish API calls that you send, and publish operations refer to the number of messages published. When publish batching is enabled, multiple messages may be sent in one publish API call, and you should expect a higher number for publish operations than publish requests if your batch size is greater than one message.

Unacked message count and oldest message age refer to the number and age of undelivered messages in your subscription. You should pay attention if they grow together and stay elevated because that would mean the service has accumulated a backlog of undeliverable or undelivered messages. When these messages in the backlog expire after the message retention period, you will risk losing them forever.

I want to tell you other cool tips and tricks about Pub/Sub, but this Medium post is getting long, so I will save them for a different time. If you have a topic that you would like me or my colleagues to write about, please leave us a comment below. Thanks for reading!

--

--