Обеспечение последовательности сообщений в Орлеане при конвейерном исполнении

У меня есть три зерна (A, B и C), выполняющие разные работы в конвейере. GrainA передаст результат в GrainB, а GrainB передаст результат в GrainC. Я хочу гарантировать последовательную отправку сообщений между последовательными зернами, что может быть достигнуто ниже.

// client code
foreach(var i in list)
{
    await grainA.job(i);
}

//grain A code
async Task job(var i)
{
    DoSomeWorkA(i);
    await grainB.job(i);
}

//grain B code
async Task job(var i)
{
    DoSomeWorkB(i);
    await grainC.job(i);
}

//grain C code
async Task job(var i)
{
    DoSomeWorkC(i);
    Console.WriteLine(i);
}

Однако проблема этого кода в том, что нет конвейерной обработки. GrainA получает сетевой объект только тогда, когда текущий объект проходит через все GrainB и GrainC (из-за оператора await). Один из способов получить конвейерную обработку - не использовать await и напрямую отправлять объекты один за другим. Однако это приводит к доставке вне очереди, как описано в эта почта.

Я хочу, чтобы выполнение было полностью конвейерным, что означает, что GrainA переходит к своему следующему заданию, когда GrainB получает результат от GrainA. Однако порядок сообщений также важен, поскольку я отправляю некоторые управляющие сообщения. Как это сделать в Орлеане?

Таким образом, вы не хотите, чтобы разные задания выполнялись одновременно, но вы не хотите, чтобы они выполнялись последовательно. Так чего ты хочешь? Какие операции можно переупорядочивать друг относительно друга, а какие нельзя?

Servy 04.08.2018 00:08

Думайте об этом как о рабочем процессе, в котором задействованы разные операторы, которые должны выполняться один за другим. Оператор добавляет к объекту что-то, что может понадобиться последующим операторам. Следовательно, операторы должны работать последовательно, но конвейерно. то есть, когда объект-1 находится в зерне C, объект-2 должен быть в зерне B, объект-3 - в зерне A.

Shengquan Ni 04.08.2018 00:26

Эти операторы сохраняют состояние? Почему порядок возврата имеет значение, если они просто полностью возвращаются вверх по стеку исходному вызывающему абоненту? Если есть какая-то последовательность, которая важна, ее нет в приведенном выше коде.

Reuben Bond 04.08.2018 09:04
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
325
1

Ответы 1

Чтобы упростить программирование и рассуждение систем с высокой степенью параллелизма, Орлеан ограничивает параллелизм и параллелизм каждого зерна (единицы вычисления и состояния) до 1. Это означает, что одновременно будет обрабатываться не более одного сообщения и не более одного потока. будет выполнять код активации заданного зерна в любой момент времени.

Это значительно упрощает то, на чем разработчик должен сосредоточиться, поскольку больше нет необходимости в примитивах синхронизации потоков, таких как блокировки.

Однако поведение можно настроить. Если вам не нужно это «безопасное» поведение по умолчанию, то вы можете пометить зерно как [Reentrant] или пометить отдельные методы как [AlwaysInterleave] в интерфейсе зерна.

Это позволяет обрабатывать множество сообщений одновременно. В каждой точке await в методе зернистости выполнение возвращается планировщику, и планировщик может начать обработку другого сообщения. Планировщик по-прежнему обеспечивает однопоточность для каждой активации зерна, поэтому блокировки по-прежнему не нужны, но сообщениям разрешено чередование в этих точках await (то есть совместная многозадачность). Это означает, что разработчику теперь необходимо рассмотреть, как внутреннее состояние может быть изменено другими запросами между этими точками await.

Для получения дополнительной информации см. Страница повторного входа в документации Орлеана.

Чтобы увеличить параллелизм (для задач, связанных с процессором), разработчик может использовать Работники без гражданства или Внешние задачи через Task.Run или аналогичный.

Также обратите внимание, что сообщения, отправленные от активации A до активации B, всегда будут отправляться по порядку независимо от конфигурации параллелизма. То же самое и для результатов, отправленных от B к A. Обратите внимание, что по-прежнему становится труднее рассуждать о порядке сообщений после увеличения параллелизма, поскольку второй вызов B может завершиться до первого вызова и, следовательно, его результат будет отправлен раньше, также. Это означает, что результаты могут быть получены не по порядку. Я полагаю, что это то, чего вы ожидаете.

Ой. это может вызвать проблему. Пожалуйста, скажите мне, правильно ли я понимаю ниже. Assume I use [Reentrant]. If grain-A makes request-1 to grain-B and awaits that, then it is free to make request-2 too to grain-B. Now in grain-B, the request-2 might arrive earlier than request-1. Thus, the message order is no more intact.

Shengquan Ni 04.08.2018 01:25

Нет, я сказал, что заявки всегда в порядке. Это ответы, которые могут быть не по порядку, потому что обработка запросов может занять разное время (и я предполагаю, что вы делаете некоторое ожидание, чтобы выполнение было выполнено, и в запросе может быть неупорядоченное чередование). Какого поведения вы пытаетесь добиться? У этих зерен есть какое-то состояние? Другими словами, можете ли вы выполнить горизонтальное масштабирование, используя работники без сохранения состояния или несколько гранул на каждом этапе?

Reuben Bond 04.08.2018 04:47

Сообщите мне, если это ответит на ваш вопрос. Мне интересно лучше понять ваш сценарий.

Reuben Bond 04.08.2018 09:46

Мы пытаемся разработать механизм обработки рабочего процесса с использованием зерен. Рабочий процесс может содержать множество операторов, таких как операторы SQL или модели машинного обучения. Каждый оператор может быть представлен зерном (однако для параллелизма у нас может быть несколько зерен на оператор). Последовательность строк проходит через этот рабочий процесс, и операторы действуют в соответствии с ними. В настоящее время мы не видим, что операторы имеют состояние (но еще рано говорить, что состояние нам не понадобится).

Shengquan Ni 04.08.2018 20:46

Мы ничего не возвращаем предыдущим операторам (поскольку строки перемещаются вперед в рабочем процессе и, наконец, помещаются в поток). Итак, нас интересует выполнение запросов у вызываемого объекта в том же порядке, в котором они вызываются вызывающим. Однако уверены ли вы в том, что запросы в порядке? Потому что в предыдущий вопрос мы видели, что выполнение на уровне зерна не было в порядке вызова на клиенте (то есть последовательность сообщений не сохраняется Орлеаном). Или ожидание меняет это поведение?

Shengquan Ni 04.08.2018 20:46

Порядок сохраняется, однако, если вы отправляете сообщения 1, 2 и 3 в зерно, возможно, что бункер, который он активирует при сбоях после сообщения 2, и зернистость повторно активируется для сообщения 3. Не ожидая каждого сообщения, вы можете гарантировать, что 1 и 2 обрабатываются до 3. Сообщения в несуществующий бункер не будут повторно отправляться автоматически. Поэтому я бы предложил либо не включать чередование (и, следовательно, обрабатывать одно сообщение за раз), либо использовать потоки для достижения желаемого поведения, либо использовать настраиваемое решение (возможно, включающее порядковые номера), чтобы гарантировать, что каждое зерно в графе обрабатывает сообщения в

Reuben Bond 04.08.2018 21:39

Опечатка: не ожидая каждого сообщения, вы можете нет гарантировать, что 1 и 2 обрабатываются раньше 3

Reuben Bond 04.08.2018 23:43

Другие вопросы по теме