#azure #azure-functions #azure-eventhub
Вопрос:
У меня есть концентратор событий и подключенная к нему функция Azure. С небольшими объемами данных все работает хорошо, но когда я протестировал его на 10 000 событиях, я получил очень странные результаты. В целях тестирования я отправляю в концентратор событий номера от 0 до 9999 и регистрирую данные в Application insights и в служебной шине. Для первого теста я вижу в Azure, что концентратор получил ровно 10 000 событий, но служебная шина и AI получили все сообщения от 0 до 4500 и каждое второе сообщение после 4500 (так что он потерял около 30%). Во втором тесте я получил все сообщения от 0 до 9999, но каждое второе сообщение между 3500 и 3200 было продублировано. Я хотел бы получить все сообщения один раз, что я сделал не так?
public async Task Run([EventHubTrigger("%EventHubName%", Connection = "AzureEventHubConnectionString")] EventData[] events, ILogger log)
{
int id = _random.Next(1, 100000);
_context.Log.TraceInfo("Started. Count: " events.Length ". " id); //AI log
foreach (var message in events)
{
//log with ASB
var mess = new Message();
mess.Body = message.EventBody.ToArray();
await queueClient.SendAsync(mess);
}
_context.Log.TraceInfo("Completed. " id); //AI log
}
Комментарии:
1. у вас включена выборка в ИИ?
2. нет, я отключил выборку
Ответ №1:
Используя события EventData [], вы считываете события из концентратора в пакетном режиме, поэтому вы видите обработку X событий одновременно, а затем в следующие секунды обрабатываете следующую партию.
Вместо EventData[] используйте просто EventData.
При отправке событий в концентратор убедитесь, что все события отправляются с одним и тем же ключом раздела, если вы хотите попробовать пакетную обработку, в противном случае они могут быть разделены на несколько разделов в зависимости от TU (единиц пропускной способности), PU (единиц обработки) и CU (единиц емкости).
Выход: До 2 МБ в секунду или 4096 событий в секунду.
Ограничения пропускной способности для базового, стандартного, Премиум-класса..:
Комментарии:
1. спасибо, что ответили! да, я знаю, что я читаю пакетами, функция обычно обрабатывает 10 событий за выполнение, но этот код должен регистрировать каждое отдельное сообщение в диапазоне от 0 до 9999 в служебной шине (всего 10 000 сообщений), верно ? но я получаю примерно 7500 сообщений в служебной шине, или иногда 10150. Похоже, в какой-то момент некоторые сообщения теряются или удваиваются, и я не понимаю, как и где..
2. Нет, вы читаете события X в зависимости от раздела концентратора. Обновленный ответ.
3. Извините, я совершенно новичок в AF и концентраторах событий, поэтому, возможно, я делаю что-то не так, но теперь я вошел в раздел AI для каждого события, и я вижу, что у них разные ключи разделов, и у меня 9550 строк вместо 10 000. Поэтому я регистрирую разные разделы, но не могу найти недостающие 450 событий. Я также попытался обработать просто данные о событиях, а не пакет, и получил это сообщение в Azure: Microsoft. Лазурь. Веб-задания. Расширения. Заглушки событий: Привязка к отдельным событиям не поддерживается. Пожалуйста, вместо этого используйте пакетную обработку путем привязки к массиву.
4. docs.microsoft.com/en-us/azure/azure-functions/… Может быть, просмотрите свои нугеты? В любом случае это замедлит вашу обработку. Как вы отправляете события в свой центр событий?
5. Я создал консольное приложение dotnet для отправки тестовых данных в концентратор событий. Кажется, это работает, я получаю ровно 10 тысяч в концентраторе событий в Azure: для (int i = 0; i CreateBatchAsync(); строковый тест = «{тест: 4, идентификатор: » i «}»; Совпадение событий. TryAdd(новые данные о событиях(кодировка.UTF8. getBytes(тест))); ждите клиента-производителя. SendAsync(совпадение событий); Консоль. линия записи(i); }
Ответ №2:
Вероятно, произойдет пара вещей, хотя я могу только строить предположения в том ограниченном контексте, который у нас есть. Вам поможет узнать больше о методологии тестирования, уровне пространства имен Концентраторов событий и количестве разделов в вашем концентраторе событий.
Первое, что следует знать,-это то, что время между моментом публикации события и моментом, когда оно доступно в разделе для чтения, не является детерминированным. Когда операция публикации завершается, брокер концентраторов событий подтверждает получение событий и берет на себя ответственность за обеспечение их сохранения в нескольких репликах и доступности в определенном разделе. Однако это не является гарантией того, что событие может быть немедленно прочитано.
В зависимости от того, как вы отправляли события, брокеру может также потребоваться маршрутизировать события из шлюза, выполняя циклический перебор или применяя алгоритм хэширования. Если вы хотите оптимизировать время от публикации до доступности, может помочь принятие на себя ответственности за распространение разделов и публикацию непосредственно в разделе, а также обеспечение того, чтобы вы публиковали с правильной степенью параллелизма для вашей среды хоста и сценария.
Что касается дублирования, важно знать, что концентраторы событий предоставляют гарантию «по крайней мере один раз»; ваше приложение-потребитель должно ожидать некоторых дубликатов и должно уметь обрабатывать их так, как это подходит для вашего сценария приложения.
Функции Azure используют набор процессоров событий в своей инфраструктуре для чтения событий. Процессоры сотрудничают друг с другом, чтобы разделить работу и распределить ответственность за разделы между ними. Поскольку сотрудничество осуществляется с использованием хранилища в качестве посредника для синхронизации, при увеличении или уменьшении масштаба экземпляров происходит наложение прав собственности на разделы, в течение которого увеличивается вероятность дублирования.
Функции принимают решение о масштабировании на основе количества событий, которые, по их мнению, ожидают чтения в разделах. В случае вашего теста, если шаблон публикации быстро увеличивается и функции видят, что «отставание по событиям» растет до такой степени, что возникает необходимость масштабирования на несколько экземпляров, вы увидите больше дублирования, чем в противном случае, в течение 10-30 секунд, пока владение разделами не нормализуется. Чтобы смягчить это, использование подхода постепенного увеличения скорости публикации в течение 1-2 минут может помочь сгладить масштабирование и уменьшить (но не устранить) дублирование.
Комментарии:
1. В зависимости от уровня вашего пространства имен, также существуют квоты для входных/выходных данных, которые могут привести к ограничению, мы пока остановимся на них.
2. Спасибо за ответ! У меня базовая ценовая категория, а количество разделов-2. Я зарегистрировал ключ раздела в AI и на самом деле вижу, как регистрируется много разных ключей. Теперь я понимаю, почему я получаю дубликаты, но почему я теряю данные?
3. Я не уверен, что вы теряете данные; вы не показали нам фрагмент того, как вы публикуете, поэтому трудно строить догадки. Базовая имеет более низкую квоту и, вероятно, будет больше подавлять. Отправка 10 000 сообщений, безусловно, займет некоторое время, и большой объем данных, отправляемых на шлюз для обработки ключа раздела, а затем маршрутизации в раздел, также займет некоторое время. Может быть, ваша публикация занимает больше времени, чем вы думаете, или в игре может быть что-то еще. Я бы предложил обновить вопрос, чтобы продемонстрировать ваш процесс публикации и рассказать нам больше о том, как вы проводите тестирование.
4. Я создал простое консольное приложение dotnet для отправки тестовых данных в концентратор событий. Кажется, это работает, я получаю ровно 10 тысяч в концентраторе событий в Azure: для (int i = 0; i CreateBatchAsync(); строковый тест = «{тест: 4, идентификатор: » i «}»; Совпадение событий. TryAdd(новые данные о событиях(кодировка.UTF8. getBytes(тест))); ждите клиента-производителя. SendAsync(совпадение событий); Консоль. WriteLine(i); } и я долго жду, чтобы убедиться, что функция Azure перестала работать, и обычно она обрабатывает около 7000-8000 сообщений из 10 000.
5. У меня также есть консольное приложение, которое получает данные из концентратора событий и отправляет их в служебную шину, и, похоже, оно работает правильно. Я получаю ровно 10 000 сообщений в служебной шине. Я использую тот же код в AF и в этом приложении (за исключением обработки смещения, в консольном приложении я использую смещение в большой двоичный объект), поэтому я чувствую, что проблема в EventHubTrigger…