Кластер

Один узел Wippy — это полноценная среда исполнения. Кластер объединяет несколько узлов в одну скоординированную систему: процессы можно именовать и достигать с любого узла, координировать через блокировки и группы, опираться на общее консенсусное ядро — и при этом код не меняет способ порождения, отправки сообщений или супервизии.

Кластеризация подключается явно (cluster.enabled). Эта страница описывает модель, которую видит ваш код; топологию, конфигурацию и эксплуатацию см. в Руководстве по кластеру.

Модель

Узлы обнаруживают друг друга через gossip (SWIM) — узел присоединяется, указывая на начальный узел (seed), а членство и обнаружение сбоев сходятся без координатора. Поверх gossip работает небольшое ограниченное ядро Raft: фиксированное множество голосующих узлов обеспечивает линеаризуемый консенсус, остальной флот использует gossip. Большинство узлов никогда не несут нагрузку консенсуса, поэтому кластер масштабируется горизонтально, сохраняя единый источник истины для тех вещей, которым он нужен.

То, что кластер даёт вашему коду, сводится к трём идеям: имена, маршрутизация и примитивы координации.

Именование

Обычно процесс адресуется по PID. В кластере он также может быть зарегистрирован под именем и доступен по этому имени откуда угодно. Единственное решение, которое имеет значение, — это область видимости: гарантия согласованности, которую вы хотите получить, с учётом её стоимости:

Область Видимость Гарантия Применение
Local этот узел мгновенно, без координации вспомогательные процессы на узле
Eventual весь кластер сходится после gossip; конфликты разрешаются с уведомлением проигравшего имена сервисов, групп и ограниченного присутствия
Consistent весь кластер линеаризуемый синглтон через Raft стандартный именованный сервис в масштабе кластера
Strong весь кластер Consistent, плюс каждый живой узел подтверждает до активации имени синглтоны плоскости управления и блокировки

Области образуют строгое упорядочение — Local < Eventual < Consistent < Strong — по оси согласованность/стоимость. Выбирайте наиболее слабую область, которая всё ещё удовлетворяет нужной гарантии. Имена регистрируются через process.registry и освобождаются автоматически при завершении владеющего процесса (или выходе его узла из кластера).

Маршрутизация

Именование полезно только тогда, когда имя надёжно достигает нужного процесса. Маршрутизация связывает эти две вещи и следует нескольким последовательным правилам:

  • Чтения локальны. Каждый узел разрешает имя из собственной реплики или кэша, распространённого через gossip — без сетевого обращения для поиска имени. Это сохраняет быстроту разрешения и работоспособность во время партиций.
  • Разрешение имеет фиксированный порядок. Имя разрешается по плоскостям по очереди — Consistent (Raft), затем Eventual (gossip), затем Local — поэтому имя в масштабе кластера перекрывает локальное с той же строкой.
  • Записи маршрутизируются к источнику авторитета. Регистрация Consistent или Strong проходит через лидера Raft; узел, не являющийся лидером, пересылает запись и ожидает результата. После фиксации активная привязка распространяется через gossip, чтобы каждый узел — включая те, что не входят в ядро Raft — мог впоследствии разрешать имя локально.
  • Сообщения маршрутизируются по PID. Когда вы вызываете process.send с именем, оно разрешается в PID и ретранслятор доставляет сообщение на владеющий узел. Ваш код адресует процесс одинаково — находится ли он на этом узле или на другом: расположение прозрачно.

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

Примитивы

Кластеризация предоставляет небольшой набор строительных блоков. Каждый подробно описан на отдельной странице; здесь — концепция и то, что они позволяют строить:

  • Членство и идентичность — актуальное множество узлов, идентичность и роль текущего узла. Используйте для обнаружения пиров или шардирования работы. См. system.cluster и system.node.
  • Состояние консенсуса — лидер Raft, терм и роль текущего узла, для диагностики и логики с учётом лидера. См. system.raft.
  • Имена в масштабе кластера — регистрация и разрешение процессов по имени и области видимости, основа, на которой строится всё остальное. См. process.registry.
  • Распределённые блокировки — взаимное исключение в масштабе кластера с не более чем одним держателем, освобождается автоматически при гибели держателя. См. system.lock.
  • Группы процессов — вступайте в именованные группы и рассылайте сообщения каждому участнику на всех узлах, в стиле Erlang. См. Группы процессов.

Эти примитивы намеренно низкоуровневы: блокировки и именованные синглтоны построены на области Strong, группы процессов — на gossip, и все они опираются на одно и то же членство и маршрутизацию, описанные выше — поэтому они предсказуемо компонуются, а не изобретают собственный способ распределения.

См. также