Skip to content

Push Subscriptions — HTTP Endpoint & Retry Mechanics

Push subscription đảo ngược vai trò: thay vì subscriber chủ động pull message, Pub/Sub đóng vai trò HTTP client và gọi vào endpoint của bạn. Mô hình này đơn giản cho các use case nhỏ — không cần duy trì long-running process, chỉ cần expose một HTTP endpoint. Nhưng ẩn bên dưới là các cơ chế kiểm soát lưu lượng phức tạp mà nếu không hiểu, bạn có thể gặp overload endpoint hoặc message tích tụ mà không xử lý được.

Cơ chế delivery: Pub/Sub như HTTP client

Message delivery flow

Khi push subscription nhận được messages mới từ topic, Pub/Sub gọi HTTP POST tới endpoint đã cấu hình:

Pub/Sub → POST /your-endpoint HTTP/1.1
Content-Type: application/json

{
  "message": {
    "data": "<base64-encoded payload>",
    "messageId": "12345",
    "publishTime": "2025-01-15T10:00:00Z",
    "attributes": {
      "key": "value"
    }
  },
  "subscription": "projects/my-project/subscriptions/my-subscription"
}

Một request = một message. Push subscriptions gửi một message per HTTP request, không batch. Đây là khác biệt lớn so với pull (có thể nhận nhiều messages cùng lúc).

Acknowledgment qua HTTP status code

Endpoint phải trả về HTTP status code để ack hoặc nack:

Ack (thành công):

  • 102, 200, 201, 202, 204 — bất kỳ code nào trong danh sách này

Nack (thất bại, redeliver):

  • Bất kỳ status code nào khác (4xx, 5xx, timeout)
  • Không trả về response trong ackDeadlineSeconds

Lưu ý: HTTP 4xx cũng trigger redeliver, không phải "không retry" như trong nhiều HTTP semantics thông thường. Pub/Sub không phân biệt 400 Bad Request với 500 Internal Server Error — cả hai đều là "nack, redeliver". Nếu message thực sự invalid và endpoint luôn trả 400, nó sẽ bị redeliver mãi cho đến khi Dead Letter Topic trigger.

HTTPS requirement

Push subscription bắt buộc HTTPS với certificate hợp lệ (không phải self-signed). Pub/Sub verify TLS certificate của endpoint. Endpoint phải:

  • Publicly reachable (hoặc qua VPC private)
  • TLS certificate valid (CA-signed, chưa expired)
  • Không dùng self-signed certificate

Với Cloud Run, Cloud Functions, App Engine — endpoint tự động đáp ứng điều kiện này. Với custom server, phải cấu hình TLS đúng cách.

Push window — slow-start algorithm và rate control

Đây là phần ít được biết nhất nhưng quan trọng nhất để hiểu behavior của push subscriptions.

Push window là gì

Pub/Sub sử dụng khái niệm push window — số lượng concurrent outstanding HTTP requests tới endpoint tại bất kỳ thời điểm nào. Pub/Sub không gửi message mới cho đến khi có "slot" trong push window trống (tức là một request đang chờ response được resolve).

Slow-start mechanism: Push window không cố định — nó tăng dần dựa trên success rate:

  • Mỗi successful delivery (HTTP 2xx): window size tăng lên
  • Mỗi failed delivery hoặc timeout: window size giảm xuống
  • Sau một số lần failure liên tiếp: Pub/Sub enter push backoff mode

Push window ceiling

Pub/Sub không publish chính xác giới hạn trên của push window, nhưng docs đề cập 3,000 outstanding messages per region là điểm mà growth trở thành linear thay vì exponential. Trong thực tế, push throughput bị giới hạn bởi:

  1. Response time của endpoint: Nếu endpoint mất 100ms/request và window = 100, throughput = 1,000 msg/s
  2. Window ceiling: Sau 3,000 outstanding, growth chậm lại
  3. Endpoint capacity: Pub/Sub sẽ không gửi nhanh hơn khả năng xử lý của endpoint

Với low-latency endpoint (< 10ms), push throughput có thể đạt cao. Với high-latency endpoint (> 1s), push window cần lớn hơn để đạt cùng throughput.

Retry mechanics và exponential backoff

Khi nào retry xảy ra

Pub/Sub retry push delivery khi:

  • Endpoint trả về HTTP status khác 2xx
  • Endpoint không trả response trong ackDeadlineSeconds
  • Network error khi kết nối tới endpoint

Push backoff — cơ chế thực tế

Khi endpoint thất bại nhiều lần liên tiếp, Pub/Sub không retry ngay lập tức — nó apply exponential backoff:

Delay range: 100ms đến 60s (theo documentation)
Sau mỗi failure: delay tăng exponentially
Sau thành công: delay reset về minimum

Quan trọng: Push backoff áp dụng globally cho toàn subscription, không per-message. Nếu endpoint đang bị quá tải và trả về 503, Pub/Sub sẽ giảm tốc độ gửi cho tất cả messages của subscription đó — kể cả messages "khỏe mạnh" có thể xử lý được.

Theo docs: "Push backoff can't be turned on or off. You also can't modify the values used to calculate the delay."

Đây là một trong các lý do push subscription ít linh hoạt hơn pull subscription trong scenarios cần fine-grained control.

Retry không có DLQ tự động (nếu không cấu hình Dead Letter Topic)

Mặc định, nếu endpoint liên tục fail, message sẽ bị redeliver mãi cho đến khi retention period hết (default 7 ngày). Message không tự động bị drop hay gửi sang DLT trừ khi bạn cấu hình Dead Letter Topic với max delivery attempts.

Authentication — JWT signing

Cơ chế

Khi cấu hình authentication cho push subscription, Pub/Sub tạo một JWT và include trong Authorization header của mỗi HTTP request:

POST /your-endpoint HTTP/1.1
Authorization: Bearer <signed-JWT>
Content-Type: application/json
...

JWT được ký bởi service account của Pub/Sub. Endpoint có thể verify JWT bằng cách:

  1. Fetch public key từ Google's public key endpoint
  2. Verify JWT signature
  3. Verify claims: iss (issuer), aud (audience phải match endpoint URL), exp (chưa expired)

Service account trong JWT: JWT email claim chứa service account được cấu hình cho push subscription. Endpoint có thể dùng claim này để verify identity và authorize.

Khi không dùng authentication

Nếu endpoint không verify JWT, bất kỳ ai biết URL đều có thể gửi fake messages. Với public endpoints, luôn enable và verify authentication. Với Cloud Run và Cloud Functions, có thể dùng GCP-native authentication thay vì manual JWT verification.

Ordering với push subscriptions

Push subscription có một ràng buộc quan trọng khi dùng ordering keys: chỉ có một outstanding message per ordering key tại bất kỳ thời điểm nào.

Điều này có nghĩa: nếu ordering key "customer-123" đang có một message được gửi tới endpoint nhưng chưa nhận ack, Pub/Sub sẽ không gửi message tiếp theo có cùng ordering key cho đến khi nhận được ack.

Throughput implication: Với nhiều ordering keys, throughput tổng vẫn cao. Nhưng với một ordering key hot (nhiều messages cho cùng key), throughput của key đó bị giới hạn bởi response time của endpoint. Nếu endpoint mất 100ms/request, throughput cho key đó là tối đa 10 msgs/s — dù endpoint nhanh đến đâu với requests của keys khác.

So sánh Push vs Pull

Đặc điểmPushPull
Ai initiate kết nốiPub/SubSubscriber
Throughput controlPub/Sub (push window)Subscriber (flow control)
Endpoint requirementPublic HTTPSKhông cần
LatencyThấp (server push)Thấp (StreamingPull)
Exactly-onceKhông hỗ trợHỗ trợ
Messages per request1Nhiều (batch)
Backpressure mechanismPush backoff (auto)maxOutstandingMessages
Ordering supportCó (1 outstanding per key)
Use case tốtServerless, event-drivenHigh-throughput, stateful processing

Khi nào chọn push vs pull

Chọn Push khi:

  • Endpoint là serverless (Cloud Functions, Cloud Run): không cần long-running process
  • Simple event processing: nhận event → xử lý → done
  • Scale-to-zero là yêu cầu quan trọng
  • Message rate không quá cao (< 10,000 msgs/s)

Chọn Pull khi:

  • Cần exactly-once delivery (push không hỗ trợ)
  • Cần fine-grained flow control (maxOutstandingMessages)
  • High-throughput (> 10,000 msgs/s): Pull batch nhiều messages hiệu quả hơn
  • Endpoint không publicly accessible
  • Cần batch processing: pull N messages, xử lý batch, ack batch
  • Cần concurrent processing: một subscription với nhiều subscriber instances

Anti-pattern phổ biến với push: Dùng push cho high-throughput workload với heavy processing. Một message per request overhead trở nên đáng kể ở scale cao. Push phù hợp với "nhẹ, nhanh, stateless" — nếu processing phức tạp, pull cho phép kiểm soát tốt hơn.

References