Глава 1 этой статьи: https://medium.com/software-engineering-problems/what-represents-the-past-present-and-future-the-future-1-665966610825

Глава 2 этой статьи: https://medium.com/software-engineering-problems/what-represents-the-past-present-and-future-9a8f8bbde4b6

Мы уже видели, насколько мощной может быть одиночная сопрограмма. Но сжимать все в одной сопрограмме — не вариант. С точки зрения управления сложностью, мы должны нырять и побеждать. Кроме того, будущее не однопоточное, мы должны описывать, как все происходит одновременно.

Многозадачность

Первый шаг — сделать так, чтобы планировщик поддерживал более одной запущенной задачи. Операционная система представляет собой планировщик потоков ОС, который поддерживает больше потоков, чем число ЦП. Но операционная система представляет собой низкоуровневый упреждающий планировщик, который довольно сложен. Здесь мы собираемся реализовать простой совместный планировщик.

lua версия: https://tio.run/

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

lua версия: https://tio.run/

Объедините будущее сна с многозадачностью, у нас есть

версия lua: https://tio.run/

es2017 await/async внутри имеет файл ready_tasks. разрешить поместить задачу в этот список. Можно сказать, что es2017 имеет встроенный цикл расписания для многозадачности.

Разложение

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

Каждая коробка здесь — сопрограмма. Оркестровка - самая простая форма:

lua версия: https://tio.run/

Положительным моментом оркестровки является простота. Следуя графу вызовов A, мы можем видеть все. Недостатком оркестровки является связанность. Если шаг 2 или шаг 3 не являются «вашим делом», вызывает раздражение их и ждет их возвращения. В этом случае поможет хореография.

lua версия: https://tio.run/

Эта форма хореографии на самом деле не устраняет связь. A знает о B, а B знает о C. Чтобы разделить их, нам нужна промежуточная служба хранения, такая как очередь сообщений или база данных.

lua версия: https://tio.run/

«A_subscribers» не является точным представлением. Реальная роль, которую играет очередь сообщений, сложна. Позже мы сделаем более точное представление.

Координация

Цель декомпозиции — разделить один линейный процесс на более мелкие блоки. Визуально блоки идут один за другим. В отличие от декомпозиции, координация обрабатывает случай, когда блоки «перекрываются» друг с другом. В целом существует два типа:

Разветвление/присоединение

Fork/join по-прежнему является оркестровкой. Скажем, начальник А поручает работу А. А делит работу на две части и делегирует своим непосредственным подчиненным В и С. В и С выполняют работу одновременно, затем А собирает результаты и отчитывается. В этом случае B и C несут ответственность, а A несет ответственность. Отличительной чертой оркестровки является четкая собственность, за все отвечает парень на самом верху.

Версия es2017: https://tio.run/

Fork/join не обязательно ждет их всех. Если на один документ нужна подпись одного ВП. Запрос может быть отправлен всем VP. Если один из них одобрен, поток может продолжаться.

Версия es2017: https://tio.run/

Есть еще вопросы, которые мы можем преследовать:

  • Что, если мы хотим подождать 2 из 3?
  • Когда promise.race вернется, что произойдет с другой все еще работающей сопрограммой? Можем ли мы отменить его?
  • Что, если одно и то же обещание ожидает более одной сопрограммы?

Коммуникация

Другой формой координации является равноправное взаимодействие нескольких параллельных задач. Эффективное сотрудничество сложно. Наличие нескольких равных команд, работающих вместе без руководства ими, часто приводит к хаосу. Эффективное сотрудничество основывается на общении.

Одна сопрограмма должна иметь возможность «вызывать» другую сопрограмму.

Версия es2017: https://tio.run/

А сам парк у планировщика. Так что, когда B вызывает A, планировщик может разбудить его. Однако предположение, что сервер запустится раньше клиента, неверно. Что, если B позвонит A до того, как A будет готов обслужить? В этом случае нам нужно припарковать клиента в планировщике.
Полная реализация: https://github.com/dexscript/scheduler.ts/blob/master/src/scheduler.ts

Теперь у нас есть способ сделать синхронный «RPC» между сопрограммами. Чтобы идентифицировать сервер, мы обновили безымянную сопрограмму до «актера» с идентификатором. Текущая реализация является однопоточной, так как javascript является однопоточным. Однако «RPC» может быть расширен для вызова реального удаленного субъекта на удаленной машине.

«Scheduler.stub» — это синтаксический сахар, который делает вызов более привлекательным.

Краткий обзор

  • Функция/объект/сопрограмма для описания процесса
  • Активный процесс — это сопрограмма с четко определенными протоколами планировщика.
  • Активный процесс очень выразительный, он может представлять полный длительный бизнес-процесс.
  • Правильный планировщик может выполнять совместную многозадачность
  • Обновите активный процесс до «актера», который может выполнять RPC между собой.

В следующей главе мы собираемся представить сложное сотрудничество с актерами.

Смотрите также

Что представляет прошлое, настоящее и будущее: будущее(2)

Что представляет прошлое, настоящее и будущее: будущее(1)

Что делает код нечитаемым

Что делает архитектуру ПО хорошей

3 роли языков программирования