GCP pubsub: Почему публикация 200 тысяч сообщений быстро приводит к 2,5 миллионам сообщений по теме - PullRequest
2 голосов
/ 06 августа 2020

Предварительные условия:

  1. У нас есть пустой топи c создан, с единой пул подпиской
  2. Нет активных подписок на подписку
  3. Мы публикуем sh около 200 тыс. Сообщений быстро, используя @google/pubsub библиотеку

Наблюдение:

Количество незапакованных сообщений

Большой скачок до 2,5 миллионов сообщений произошел, когда мы опубликовали сообщения с использованием приведенного ниже эквивалента кода. Из сообщения журнала мы видим, что он думает, что опубликовал 200 тыс. Сообщений.

Вторые небольшие удары были, когда мы взяли приведенный ниже код, но разделили вызовы Promise.all с другим для l oop и дали только pubsub sdk 1000 сообщений за раз.

Код:

import {PubSub} from '@google-cloud/pubsub';

const pubsub = new PubSub()
const topic = pubsub.topic("some-topic");

async function publish(message) {
    const dataBuffer = Buffer.from(JSON.stringify(data));
    return topic.publisher.publish(dataBuffer, metadata);
}

async function processThing(thing) {
    const parsed = parseThingToLotsOfThings(thing);

    return (await Promise.all(
        parsed.map(it => topic.publish(it))
    )).length
}

async function processThings(things) {
    let count = 0;

    for (const thing of things) {
        count += await processThing(thing);
    }

    console.log(`published ${count} messages`);
}

Прочитав исходный код nodejs sdk и просмотрев ссылку на API, я не Не понимаю, как это происходит.

Я понимаю, что это гарантия хотя бы одной доставки, но это на порядок больше, и внутренне клиент включает только 100 сообщений на публикацию sh rp c, поэтому я не понимаю, почему пакетирование его в нашем коде изменило бы поведение.

Это ошибка в sdk, или мы должны пакетировать вещи перед вызовом sdk?

1 Ответ

1 голос
/ 06 августа 2020

Я подозреваю, что происходит то, что внезапный приток сообщений 200K приводит к перегрузке ресурсов на клиенте (это может быть сеть, ЦП или пулы потоков). В результате сообщения отправляются на сервер, но клиент слишком загружен, чтобы своевременно обрабатывать ответы. В результате он пытается снова отправить сообщения, что приводит к дублированию и увеличению объема работы для клиента.

Я бы рекомендовал два решения:

  1. По возможности масштабируйте по горизонтали. Распределите нагрузку на большее количество издателей, чтобы не перегружать отдельных клиентов.

  2. Ограничьте количество одновременных публикаций, отслеживая количество невыполненных фьючерсов. Самый простой способ сделать это - использовать семафор . Некоторые клиентские библиотеки Cloud Pub / Sub уже поддерживают установку этих ограничений в самой библиотеке, например, Java. Я предполагаю, что это функциональность, которая в конечном итоге войдет и в библиотеку node.js.

...