Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Orleans предоставляет управление кластерами с помощью встроенного протокола членства, иногда называемого членством в кластере. Цель этого протокола — чтобы все силосы (Orleans серверов) согласовали набор активных силосов, обнаруживали неработоспособные силосы и позволяли новым силосам присоединяться к кластеру.
Конфигурация протокола членства
Протокол членства использует следующую конфигурацию по умолчанию:
- Каждый силос контролируется 10 другими силосами
- 2 подозрения требуются для объявления силоса мертвым
- Подозрения действительны в течение 3 минут
- Пробы отправляются каждые 10 секунд
- 3 пропущенные пробы вызывают подозрение
По умолчанию обычное время обнаружения сбоев составляет около 15 секунд. В сценариях восстановления после сбоев, когда силосы выходят из строя без должной очистки, кластер восстанавливается с использованием метки времени IAmAlive (обновляется каждые 30 секунд по умолчанию); силосы, не обновившие метку времени в течение нескольких периодов, игнорируются при запуске на этапе проверки подключения. Пропуская эти неотвечающие силосы, новые силосы могут запускаться и быстро очищать кластер устаревших силосов, объявляя их мертвыми.
Конфигурация
Параметры протокола членства можно настроить с помощью ClusterMembershipOptions:
siloBuilder.Configure<ClusterMembershipOptions>(options =>
{
// Number of silos each silo monitors (default: 10)
options.NumProbedSilos = 10;
// Number of suspicions required to declare a silo dead (default: 2)
options.NumVotesForDeathDeclaration = 2;
// Time window for suspicions to be valid (default: 180 seconds)
options.DeathVoteExpirationTimeout = TimeSpan.FromSeconds(180);
// Interval between probes (default: 10 seconds)
options.ProbeTimeout = TimeSpan.FromSeconds(10);
// Number of missed probes before suspecting a silo (default: 3)
options.NumMissedProbesLimit = 3;
});
Когда следует настроить параметры
В большинстве случаев параметры по умолчанию подходят. Однако в следующих сценариях можно рассмотреть возможность корректировки:
-
Сети с высокой задержкой. Увеличьте
ProbeTimeoutраспределение силосов между регионами с высокой задержкой сети. -
Критически важные требования к доступности: уменьшите
DeathVoteExpirationTimeoutдля ускорения обнаружения сбоев, но будьте осторожны с ложными срабатываниями.
Конфигурация протокола членства
Протокол членства использует следующую конфигурацию по умолчанию:
- Каждый силос отслеживается тремя другими силосами
- 2 подозрения требуются для объявления силоса мертвым
- Подозрения действительны в течение 3 минут
- Пробы отправляются каждые 10 секунд
- 3 пропущенные пробы вызывают подозрение
Конфигурация протокола членства
Протокол членства использует следующую конфигурацию по умолчанию:
- Каждый силос отслеживается тремя другими силосами
- 2 подозрения требуются для объявления силоса мертвым
- Подозрения действительны в течение 3 минут
Протокол использует внешнюю службу для предоставления абстракции IMembershipTable.
IMembershipTable является плоской, устойчивой таблицей, используемой для двух целей. Во-первых, он служит точкой встречи, с помощью которой силосы могут найти друг друга и Orleans клиенты могут найти силосы. Во-вторых, он сохраняет текущее представление об участниках (список активных узлов) и помогает координировать достижение консенсуса по этому представлению.
В настоящее время доступны следующие официальные реализации IMembershipTable :
- ADO.NET (PostgreSQL, MySQL/MariaDB, SQL Server, Oracle)
- AWS DynamoDB,
- Apache Cassandra,
- Apache ZooKeeper,
- Azure Cosmos DB,
- Хранилище таблиц Azure,
- ХашиКорп Consul,
- Redis,
- и реализация в оперативной памяти для разработки.
Настройка кластеризации Redis
Настройте Redis в качестве поставщика кластеризации с помощью UseRedisClustering метода расширения:
using StackExchange.Redis;
var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleans(siloBuilder =>
{
siloBuilder.UseRedisClustering(options =>
{
options.ConfigurationOptions = new ConfigurationOptions
{
EndPoints = { "localhost:6379" },
AbortOnConnectFail = false
};
});
});
Кроме того, можно использовать строку подключения:
siloBuilder.UseRedisClustering("localhost:6379");
Класс RedisClusteringOptions предоставляет следующие параметры конфигурации:
| Недвижимость | Тип | Description |
|---|---|---|
ConfigurationOptions |
ConfigurationOptions |
Конфигурация клиента StackExchange.Redis. Обязательное. |
EntryExpiry |
TimeSpan? |
Необязательное время окончания срока действия для записей. Это можно задать только для временных сред, таких как тестирование. По умолчанию — null. |
CreateMultiplexer |
Func<RedisClusteringOptions, Task<IConnectionMultiplexer>> |
Кастомная фабрика для создания мультиплексера подключения Redis. |
CreateRedisKey |
Func<ClusterOptions, RedisKey> |
Пользовательская функция для создания ключа Redis для таблицы членства. Формат по умолчанию — {ServiceId}/members/{ClusterId}. |
Это важно
IMembershipTable Реализации интерфейса должны использовать устойчивое хранилище данных. Например, если вы используете Redis, убедитесь, что сохраняемость включена явным образом. Переменные конфигурации могут привести к недоступности кластера.
Интеграция .NET Aspire для кластеризации
При использовании .NET Aspire можно настроить Orleans кластеризацию декларативно в проекте AppHost. Aspire автоматически внедряет необходимую конфигурацию в проекты silo с помощью переменных среды.
Кластеризация Redis с помощью Aspire
Проект AppHost (Program.cs):
var builder = DistributedApplication.CreateBuilder(args);
var redis = builder.AddRedis("redis");
var orleans = builder.AddOrleans("cluster")
.WithClustering(redis);
builder.AddProject<Projects.MySilo>("silo")
.WithReference(orleans)
.WithReference(redis);
builder.Build().Run();
Проект Silo (Program.cs):
var builder = Host.CreateApplicationBuilder(args);
builder.AddServiceDefaults();
builder.AddKeyedRedisClient("redis");
builder.UseOrleans();
builder.Build().Run();
Кластеризация хранилища таблиц Azure с помощью Aspire
Проект AppHost (Program.cs):
var builder = DistributedApplication.CreateBuilder(args);
var storage = builder.AddAzureStorage("storage")
.RunAsEmulator(); // Use Azurite for local development
var tables = storage.AddTables("clustering");
var orleans = builder.AddOrleans("cluster")
.WithClustering(tables);
builder.AddProject<Projects.MySilo>("silo")
.WithReference(orleans)
.WaitFor(storage);
builder.Build().Run();
Проект Silo (Program.cs):
var builder = Host.CreateApplicationBuilder(args);
builder.AddServiceDefaults();
builder.AddKeyedAzureTableServiceClient("clustering");
builder.UseOrleans();
builder.Build().Run();
Подсказка
Чтобы использовать эмулятор Azurite для локальной разработки, вызовите .RunAsEmulator() на ресурсе хранилища Azure. Без этого вызова Aspire ожидает реального подключения к хранилищу данных Azure.
Кластеризация Azure Cosmos DB с помощью Aspire
Проект AppHost (Program.cs):
var builder = DistributedApplication.CreateBuilder(args);
var cosmos = builder.AddAzureCosmosDB("cosmos")
.RunAsEmulator(); // Use emulator for local development
var database = cosmos.AddCosmosDatabase("orleans");
var orleans = builder.AddOrleans("cluster")
.WithClustering(database);
builder.AddProject<Projects.MySilo>("silo")
.WithReference(orleans)
.WaitFor(cosmos);
builder.Build().Run();
Проект Silo (Program.cs):
var builder = Host.CreateApplicationBuilder(args);
builder.AddServiceDefaults();
builder.AddKeyedAzureCosmosClient("cosmos");
builder.UseOrleans();
builder.Build().Run();
Замечание
Интеграция Aspire с Cosmos DB для Orleans в настоящее время поддерживает только кластеризацию. Для хранения зерна и напоминаний с помощью Cosmos DB необходимо вручную настроить этих поставщиков в проекте silo.
Это важно
Необходимо вызвать соответствующий AddKeyed* метод (например AddKeyedRedisClient, AddKeyedAzureTableServiceClientили AddKeyedAzureCosmosClient) для регистрации резервного ресурса в контейнере внедрения зависимостей.
Orleans Поставщики ищут ресурсы по имени службы с ключом, если пропустить этот шаг, Orleans не сможет разрешить ресурс и вызовет ошибку разрешения зависимостей во время выполнения.
Дополнительную информацию о
Настройка кластеризации Cassandra
Настройте Apache Cassandra в качестве поставщика кластеризации с помощью UseCassandraClustering метода расширения. Установите Microsoft.Orleans.Clustering.Cassandra пакет NuGet:
dotnet add package Microsoft.Orleans.Clustering.Cassandra
Настройте кластеризацию Cassandra со строкой подключения:
using Orleans.Clustering.Cassandra.Hosting;
var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleans(siloBuilder =>
{
siloBuilder.UseCassandraClustering(
connectionString: "Contact Points=localhost;Port=9042",
keyspace: "orleans");
});
Кроме того, используйте конфигурацию на основе параметров для получения дополнительных элементов управления:
siloBuilder.UseCassandraClustering(options =>
{
options.ConfigureClient("Contact Points=cassandra-node1,cassandra-node2;Port=9042", "orleans");
options.UseCassandraTtl = true;
options.InitializeRetryMaxDelay = TimeSpan.FromSeconds(30);
});
Или укажите настраиваемую фабрику сеансов для расширенных сценариев:
using Cassandra;
siloBuilder.UseCassandraClustering(async serviceProvider =>
{
var cluster = Cluster.Builder()
.AddContactPoints("cassandra-node1", "cassandra-node2")
.WithPort(9042)
.WithCredentials("username", "password")
.WithQueryOptions(new QueryOptions().SetConsistencyLevel(ConsistencyLevel.Quorum))
.Build();
return await cluster.ConnectAsync("orleans");
});
Класс CassandraClusteringOptions предоставляет следующие параметры конфигурации:
| Недвижимость | Тип | По умолчанию | Description |
|---|---|---|---|
UseCassandraTtl |
bool |
false |
При true, настройка времени жизни для строк таблицы членства в Cassandra позволяет очистить устаревшие силосы, даже если кластер больше не функционирует. Используется DefunctSiloExpiration из ClusterMembershipOptions. |
InitializeRetryMaxDelay |
TimeSpan | 20 секунд | Максимальная задержка между повторными попытками при возникновении состязаний во время инициализации. Например, это обычно необходимо при подключении большого количества узлов одновременно к кластерам Cassandra с многими центрами обработки данных. |
Когда следует использовать кластеризацию Cassandra
Рассмотрим Cassandra для кластеризации, когда:
- У вас уже есть инфраструктура Cassandra в вашей организации
- Вам нужен поставщик кластеризации, работающий в нескольких центрах обработки данных с настраиваемой согласованностью
- Требуется автоматическая очистка устаревших silo с помощью TTL Cassandra, даже когда Orleans кластер не функционирует.
- Для больших кластеров требуется высокая пропускная способность записи
Настройка кластеризации Azure Cosmos DB
Настройте Azure Cosmos DB в качестве поставщика кластеризации с помощью UseCosmosClustering метода расширения. Установите Microsoft.Orleans.Clustering.Cosmos пакет NuGet:
dotnet add package Microsoft.Orleans.Clustering.Cosmos
Настройка кластеризации Cosmos DB с использованием строки подключения.
using Azure.Identity;
var builder = Host.CreateApplicationBuilder(args);
builder.UseOrleans(siloBuilder =>
{
siloBuilder.UseCosmosClustering(options =>
{
options.ConfigureCosmosClient(
"https://myaccount.documents.azure.com:443/",
new DefaultAzureCredential());
options.DatabaseName = "Orleans";
options.ContainerName = "OrleansCluster";
options.IsResourceCreationEnabled = true;
});
});
Кроме того, можно использовать строку подключения:
siloBuilder.UseCosmosClustering(options =>
{
options.ConfigureCosmosClient("AccountEndpoint=https://myaccount.documents.azure.com:443/;AccountKey=...");
});
Класс CosmosClusteringOptions наследует от CosmosOptions и предоставляет следующие параметры конфигурации:
| Недвижимость | Тип | По умолчанию | Description |
|---|---|---|---|
DatabaseName |
string |
"Orleans" |
Имя базы данных Cosmos DB. |
ContainerName |
string |
"OrleansCluster" |
Имя контейнера для данных членства в кластере. |
IsResourceCreationEnabled |
bool |
false |
При trueавтоматическом создании базы данных и контейнера, если они не существуют. |
DatabaseThroughput |
int? |
null |
Зарезервированная пропускная способность для базы данных. Если nullиспользуется бессерверный режим. |
ContainerThroughputProperties |
ThroughputProperties? |
null |
Свойства пропускной способности контейнера. |
ClientOptions |
CosmosClientOptions |
new() |
Параметры, переданные клиенту Cosmos DB. |
CleanResourcesOnInitialization |
bool |
false |
Удаляет базу данных при инициализации. Только для тестирования. |
Когда использовать кластеризацию в Cosmos DB
Рассмотрим Azure Cosmos DB для кластеризации, когда:
- Вы уже используете Azure Cosmos DB в приложении
- Требуется глобально распределенная база данных с возможностями записи в нескольких регионах
- Требуется вариант полностью управляемого, бессерверного решения с автоматическим масштабированием.
- Вам требуется низкая задержка операций чтения и записи с гарантированными SLA.
Для Orleans клиентов используйте UseCosmosGatewayListProvider для настройки обнаружения шлюза:
builder.UseOrleansClient(clientBuilder =>
{
clientBuilder.UseCosmosGatewayListProvider(options =>
{
options.ConfigureCosmosClient(
"https://myaccount.documents.azure.com:443/",
new DefaultAzureCredential());
});
});
Кроме того IMembershipTable, каждый силос участвует в полностью распределенном одноранговом протоколе членства, который обнаруживает неработающие силосы и приходит к согласию о списке живых силосов. Ниже описана внутренняя реализация Orleansпротокола членства.
Протокол членства
При запуске каждый silo добавляет запись для себя в общеизвестную общую таблицу с помощью реализации IMembershipTable. Orleans использует сочетание идентификатора silo (
ip:port:epoch) и идентификатора развертывания службы (идентификатор кластера) в качестве уникальных ключей в таблице. Эпоха — это просто время при запуске этого разбиения, обеспечиваяip:port:epochуникальность в заданном Orleans развертывании.Силосы отслеживают друг друга непосредственно через опросы приложений ("вы живы?").
heartbeatsПроверки отправляются в виде прямых сообщений из силоса в силос по тем же сокетам TCP, которые используются для регулярного обмена данными. Таким образом, пробы полностью коррелируют с фактическими проблемами сети и работоспособностью сервера. Каждый силос сканирует настраиваемый набор других силосов. Силос выбирает, кого следует исследовать, вычисляя согласованные хэши по идентификаторам других силосов, формируя виртуальное кольцо всех идентификаторов и выбирая X следующих силосов на кольце. (Это хорошо известный распределенный метод, называемый согласованным хэшированием и широко используется во многих распределенных хэш-таблицах, таких как Хорд DHT).Если silo S не получает ответы пробы Y от отслеживаемого сервера P, он подозревает P, записывая своё подозрение с временным штампом в строку P в
IMembershipTable.Если P имеет более Z подозрений в течение K секунд, S записывает, что P умер в строке P и распространяет моментальный снимок текущей таблицы членства всем остальным хранилищам. Силосы периодически обновляют таблицу, поэтому создание снимка состояния служит оптимизацией, позволяющей сократить время, необходимое всем силосам, чтобы узнать о новом представлении членства.
Дополнительные сведения:
Подозрение записывается
IMembershipTableв специальный столбец, соответствующий P. Когда S подозревает P, он пишет: "в момент TTT S подозревал P".Одно подозрение не достаточно, чтобы объявить P мертвым. Вам нужны подозрения Z из разных силосов в настраиваемом окне времени T (обычно 3 минуты), чтобы объявить P мертвым. Подозрение записывается с помощью контроля оптимистического параллелизма, предоставленного
IMembershipTable.Подозреваемый silo S считывает строку P.
Если
Sпоследний подозреваемый (уже были подозреваемые Z-1 в течение периода T, как записано в столбце подозрений), S решает объявить P мертвым. В этом случае S добавляет себя в список подозревателей и также записывает в столбец статуса P, что P мертв.В противном случае, если S не является последним подозреваемым, S просто добавляет себя в столбец подозреваемого.
В любом случае, обратная запись использует номер версии или ETag, прочитанные ранее, для последовательной записи обновлений в эту строку. Если запись ошибается из-за несоответствия версии или ETag, S повторяет попытку (считывает заново и пытается записать, если P уже не был помечен как завершённый).
На высоком уровне эта последовательность "чтение, локальное изменение, обратная запись" — это транзакция. Однако транзакции хранилища не обязательно используются. Код "transaction" выполняется локально на сервере, и оптимистическая согласованность, обеспечиваемая
IMembershipTable, гарантирует изоляцию и атомарность.
Каждый узел периодически считывает всю таблицу членства для своего развертывания. Таким образом, силосы узнают о новых силосах, присоединяющихся к сети, и о других силосах, признанных неактивными.
Рассылка снимков состояния: Чтобы уменьшить частоту операций чтения периодических таблиц, каждый раз, когда силос записывает данные в таблицу (подозрение, новое соединение и т. д.), он отправляет моментальный снимок текущего состояния таблицы всем остальным силосам. Так как таблица членства согласована и монотонно версиионна, каждое обновление создает уникально версиионованный моментальный снимок, которым можно безопасно делиться. Это позволяет мгновенно распространять изменения членства без ожидания периодического цикла чтения. Периодическое чтение по-прежнему сохраняется в качестве резервного механизма в случае сбоя распределения моментальных снимков.
Упорядоченные представления членства: протокол членства гарантирует, что все конфигурации членства глобально полностью упорядочены. Это упорядочение обеспечивает два ключевых преимущества:
гарантированное подключение. Когда новый узел присоединяется к кластеру, он должен проверить двустороннее подключение к каждому другому активному узлу. Если существующее хранилище не отвечает (потенциально указывающая на проблему сетевого подключения), новое хранилище не допускается к присоединению. Это обеспечивает полную связь между всеми силосами в кластере при запуске. См. примечание
IAmAliveниже об исключении в сценариях аварийного восстановления.Согласованные обновления каталогов: протоколы высокого уровня, такие как распределенный каталог зерна, полагаются на то, что все силосы имеют согласованное, монотонное представление членства. Это обеспечивает более интеллектуальное разрешение повторяющихся активаций зерна. Для получения более подробной информации обратитесь к документации каталога Grain.
Сведения о внедрении:
IMembershipTableтребует атомарных обновлений, чтобы гарантировать глобальный общий порядок изменений:- Реализации должны обновлять как записи таблицы (список силосов), так и номер версии атомарным образом.
- Это можно сделать с помощью транзакций базы данных (как в SQL Server) или атомарных операций сравнения и переключения с помощью ETags (как в хранилище таблиц Azure).
- Конкретный механизм зависит от возможностей базовой системы хранения.
Специальная строка версии членства в таблице отслеживает изменения:
- Каждая запись в таблицу (подозрения, объявления о смерти, соединения) увеличивает этот номер версии.
- Все записи сериализуются по этой строке с помощью атомарных обновлений.
- Монотонно увеличивающаяся версия обеспечивает общее упорядочение всех изменений членства.
Когда silo S обновляет состояние silo P:
- S сначала считывает последнее состояние таблицы.
- В одной атомарной операции он обновляет строку P и увеличивает номер версии.
- Если атомарное обновление завершается ошибкой (например, из-за параллельных изменений), операция повторяется с экспоненциальной задержкой.
рекомендации по масштабируемости:
Сериализация всех операций записи через версионную строку может повлиять на масштабируемость из-за возросшего конфликтов. Протокол доказал эффективность в производстве до 200 силосов, но может столкнуться с проблемами, превышающими тысячу силосов. Для очень крупных развертываний другие части Orleans (обмен сообщениями, каталог grain, хостинг) остаются масштабируемыми, даже если обновления членства становятся узким местом.
Конфигурация по умолчанию: Конфигурация по умолчанию была настроена вручную во время использования в производственной среде в Azure. По умолчанию: каждый силос отслеживается тремя другими силосами, два подозрения достаточно, чтобы объявить сило мертвым, и подозрения рассматриваются только за последние три минуты (в противном случае они устарели). Зонды отправляются каждые десять секунд, и нужно пропустить три зонда, чтобы заподозрить силос.
Самоконтроль: Детектор сбоев включает идеи из исследования Lifeguard компании Hashicorp (статья, доклад, блог) для повышения стабильности кластера во время катастрофических событий, при которых большая часть кластера испытывает частичный сбой. Компонент
LocalSiloHealthMonitorоценивает работоспособность каждого силоса с помощью нескольких эвристик.- Активное состояние в таблице членства
- Никаких подозрений от других силосов
- Последние успешные ответы запросов
- Последние полученные исследовательские запросы
- Скорость отклика пула потоков (рабочие элементы, выполняемые в течение 1 секунды)
- Точность таймера (запуск в течение 3 секунд по расписанию)
Оценка работоспособности силоса влияет на время ожидания пробы: неработоспособные силосы (оценка 1-8) увеличили время ожидания по сравнению со здоровыми силосами (оценка 0). Это обеспечивает два преимущества:
- Увеличивает время для успешного завершения проверок, когда сеть или система находится в стрессовом состоянии.
- Делает более вероятным, что неработоспособные силосы будут признаны неактивными, прежде чем они смогут неправильно исключить здоровые силосы.
Это особенно важно во время таких сценариев, как голодание пула потоков, где медленные узлы могут неправильно подозревать здоровые узлы просто потому, что они не могут обрабатывать ответы достаточно быстро.
Косвенное тестирование: еще одна функция, вдохновленная Lifeguard, повышает точность обнаружения сбоев, уменьшая вероятность того, что неработоспособный или секционированный силос неправильно объявит здоровый силос мертвым. Когда в аналитическом блоке остаётся две попытки проверки для целевого силоса до подачи голоса об объявлении его мёртвым, используется косвенное зондирование.
- Хранилище мониторинга случайным образом выбирает другой силос в качестве посредника и просит его проверить цель.
- Посредник пытается связаться с целевой шахтой.
- Если целевой объект не может реагировать в течение периода ожидания, посредник отправляет отрицательное подтверждение.
- Если хранилище мониторинга получает отрицательное подтверждение от посредника, а посредник объявляет себя здоровым (через самоконтроль, описанный выше), хранилище мониторинга отправляет голос, чтобы объявить цель мёртвой.
- При настройке по умолчанию двух обязательных голосов отрицательное подтверждение от косвенного зонда учитывается как оба голоса, что позволяет ускорить объявление мертвых силосов, когда несколько перспектив подтверждают ошибку.
Применение идеального обнаружения сбоев: как только силос объявляется мертвым в таблице, все его считают мертвым, даже если он не на самом деле мертв (например, просто временно разделён или сообщения о состоянии потерялись). Все перестают взаимодействовать с ним. После того как silo определит, что он неактивен (считывая новое состояние из таблицы), оно завершает процесс. Следовательно, инфраструктура должна быть создана для перезапуска хранилища как нового процесса (при запуске генерируется новый номер эпохи). При размещении в Azure это происходит автоматически. В противном случае требуется другая инфраструктура, например служба Windows, настроенная для автоматического перезапуска при сбое или развертывании Kubernetes.
Что происходит, если таблица недоступна в течение некоторого времени:
Если служба хранилища отключена, недоступна или возникают проблемы с коммуникацией, протокол не ошибочно объявляет силосы недоступными. Операционные оси продолжают работать без проблем. Тем не менее, Orleans не сможет объявить силос мертвым (если он обнаружит мертвый силос через пропущенные пробы, он не сможет записать эту информацию в таблицу) и не сможет позволить новым силосам присоединиться. Таким образом, полнота страдает, но точность не страдает — секционирование из таблицы никогда не приводит к ошибочному объявлению сило мертвым. Кроме того, в частичной сегментации сети (где некоторые силосы могут получить доступ к таблице, а другим это не удается), Orleans может объявить какой-то силос мертвым, но требуется время, чтобы все остальные силосы узнали об этом. Обнаружение может быть отложено, но Orleans никогда неправильно не отключает силос из-за недоступности таблицы.
IAmAliveзаписывает данные для диагностики и аварийного восстановления:Помимо сигналов пульсации, отправляемых между силосами, каждый силос периодически обновляет метку времени "Я жив" в своей строке таблицы. Это служит двумя целями:
Диагностика: Предоставляет системным администраторам простой способ проверки работоспособности кластера и определения, когда последний раз был активен силос. Метка времени по умолчанию обновляется каждые 30 секунд.
Аварийное восстановление: если силос не обновил метку времени в течение нескольких периодов (настроено с помощью
NumMissedTableIAmAliveLimit— по умолчанию: 3), новые силосы игнорируют его во время проверок подключения запуска. Это позволяет кластеру восстанавливаться после сбоев силосов, когда они происходят без надлежащей очистки.
Таблица членства
Как уже упоминалось, IMembershipTable служит в качестве точки свидания для силосов, чтобы найти друг друга и для Orleans клиентов, чтобы найти силосы. Он также помогает координировать согласие по вопросу взгляда на членство.
В следующем списке содержатся заметки о реализации некоторых официальных реализаций IMembershipTable:
Хранилище таблиц Azure: В этой реализации идентификатор развертывания Azure служит ключом раздела, а идентификатор сило (
ip:port:epoch) выступает в качестве ключа строки. Вместе они гарантируют уникальный ключ для каждого силоса. Для управления параллелизмом используется оптимистичное управление параллелизмом на основе ETags таблицы Azure. Каждый раз, когда данные считываются из таблицы, ETag для каждой прочитанной строки хранится и используется при попытке обратной записи. Служба таблиц Azure автоматически назначает и проверяет ETags на каждой записи. Для транзакций с несколькими строками используется поддержка пакетных транзакций, предоставляемых таблицей Azure , гарантируя сериализуемые транзакции по строкам с тем же ключом секции.SQL Server: В этой реализации настроенный идентификатор развертывания позволяет различать развертывания и определять, какие компоненты принадлежат каким развертываниям. Идентификатор silo определяется как сочетание
deploymentID, ip, port, epochв соответствующих таблицах и столбцах. Реляционный бэкенд использует контроль оптимистического параллелизма и транзакции, аналогичные использованию ETags в реализации таблицы Azure. Реляционная реализация ожидает, что ядро СУБД создаст ETag. Для SQL Server 2000 созданный ETag получается из вызоваNEWID(). В SQL Server 2005 и более поздних версиях используется ROWVERSION . Orleans считывает и записывает реляционные ETags в виде непрозрачныхVARBINARY(16)тегов и сохраняет их в памяти в виде строк в кодировке Base64 . Orleans поддерживает вставку нескольких строк с помощьюUNION ALL(для Oracle, включаяDUAL), которая в настоящее время используется для вставки статистических данных. Точную реализацию и обоснование SQL Server можно найти на CreateOrleansTables_SqlServer.sql.Apache ZooKeeper: В этой реализации настроенный идентификатор развертывания используется в качестве корневого узла и идентификатор силоса (
ip:port@epoch) в качестве дочернего узла. Вместе они гарантируют уникальный путь для каждого силоса. Для управления параллелизмом используется оптимистичное управление параллелизмом на основе версии узла. Каждый раз, когда данные считываются из корневого узла развертывания, версия для каждого дочернего узла silo сохраняется и используется при попытке записи обратно. Каждый раз при изменении данных узла служба ZooKeeper атомарно увеличивает номер версии. Для транзакций с несколькими строками используется метод multi, который гарантирует сериализуемые транзакции на узлах silo с тем же родительским узлом развертывания.HashiCorp Consul: хранилище ключей и значений consul использовалось для реализации таблицы членства. Дополнительные сведения см. в статье "Развертывание Consul".
AWS DynamoDB: в этой реализации идентификатор развертывания кластера используется в качестве ключа секции и идентификатора Silo (
ip-port-generation) в качестве RangeKey, что делает запись уникальной. Оптимистическая параллельность достигается с помощью атрибутаETag, делая условные записи в DynamoDB. Логика реализации довольно похожа на службу хранилища таблиц Azure.Apache Cassandra: В этой реализации композиция идентификатора службы и идентификатора кластера служит ключом партиции, а идентификатор хранилища (
ip:port:epoch) в качестве ключа строки. Вместе они обеспечивают уникальную строку для каждого силоса. Для управления параллелизмом используется оптимистичный контроль параллелизма на основе версии статического столбца с использованием легкой транзакции. Этот столбец версии используется для всех строк в секции или кластере, предоставляя согласованный добавочный номер версии для таблицы членства в каждом кластере. В этой реализации нет транзакций с несколькими строками.Эмуляция в памяти для установки разработки: для этой реализации используется специальное системное зерно. Это зерно хранится в выделенном первичном силосе, который используется только для настройки разработки. В любой реальной рабочей среде основное хранилище не требуется.
Обоснование проектирования
Естественный вопрос возникает, почему бы не полагаться полностью на Apache ZooKeeper или etcd для реализации членства в кластере, потенциально используя встроенную поддержку членства в группе с эфемерными узлами в ZooKeeper? Почему мы реализуем протокол членства? Были в первую очередь три причины:
Развертывание и размещение в облаке:
Zookeeper не является облачным сервисом. Это означает, Orleans что в облачной среде клиентам придется развертывать, запускать и управлять их экземпляром кластера ZK. Это ненужное бремя, которое не было навязано клиентам. Используя таблицу Azure, Orleans использует размещенную управляемую службу, что упрощает жизнь клиентов. В основном в облаке используйте облако как платформу, а не инфраструктуру. С другой стороны, при запуске локальной среды и управлении серверами, использование ZK в качестве реализации
IMembershipTableявляется жизнеспособным вариантом.Прямое обнаружение сбоев:
При использовании членства в группе ZK с эфемерными узлами, обнаружение сбоев происходит между серверами Orleans (клиентами ZK) и ZK-серверами. Это может не обязательно коррелировать с фактическими проблемами сети между Orleans серверами. Желание было в том, что обнаружение сбоев точно отражает состояние взаимодействия внутри кластера. В частности, в этой модели, если Orleans silo не может взаимодействовать с
IMembershipTable, оно не считается вышедшим из строя и может продолжать работу. В отличие от этого, если было использовано членство в группах ZK с временными узлами, отключение от сервера ZK может привести Orleans к тому, что клиент Silo (ZK) будет объявлен мертвым, в то время как он может быть жив и полностью функциональным.Переносимость и гибкость:
В рамках философии Orleans, Orleans не навязывает сильную зависимость от какой-либо конкретной технологии, а предлагает гибкий дизайн, в котором различные компоненты можно легко заменить на разные реализации. Именно для этой цели и служит абстракция
IMembershipTable.
Свойства протокола членства
Может обрабатывать любое количество сбоев:
Этот алгоритм может обрабатывать любое количество сбоев (f<=n), включая полный перезапуск кластера. Это контрастирует с "традиционными" решениями на основе Paxos, которые требуют кворума (обычно большинство). Производственные ситуации показали сценарии, в которых более половины силосов не работали. Эта система остается функциональной, в то время как членство на основе Paxos не сможет добиться прогресса.
Нагрузка на таблицу очень слабая
Реальные тесты проходят непосредственно между серверами, а не к таблице. Маршрутизация зондов через таблицу приведет к значительному увеличению трафика и будет менее точной с точки зрения обнаружения отказов – если сайло не сможет связаться с таблицей, оно не сможет записать свой сигнал "я жив", и другие узлы объявят его мертвым.
Настраиваемая точность против полноты
Хотя вы не можете достичь и идеальной, и точной диагностики сбоев, вы обычно хотите иметь возможность балансировать точность (не желая объявлять живой силос мёртвым) с полнотой (стремясь объявить мёртвый силос мёртвым как можно скорее). Конфигурируемые голосования для объявления мертвых и пропущенных проб позволяют обмениваться этими двумя аспектами. Дополнительные сведения см. в Университет Йель: детекторы отказов компьютерных систем.
Масштабирование:
Протокол может обрабатывать тысячи, вероятно, даже десятки тысяч серверов. Это контрастирует с традиционными решениями на основе Paxos, такими как протоколы групповой связи, которые, как известно, не масштабируются за десятки узлов.
Диагностика:
Таблица также очень удобна для диагностики и устранения неполадок. Системные администраторы могут мгновенно найти текущий список живых силосов в таблице, а также просмотреть историю всех убитых силосов и подозрений. Это особенно полезно при диагностике проблем.
Почему надежное постоянное хранилище, необходимое для реализации
IMembershipTable:Постоянное хранилище используется для
IMembershipTableв двух целях. Во-первых, он служит точкой встречи, с помощью которой силосы могут найти друг друга и Orleans клиенты могут найти силосы. Во-вторых, надежное хранилище помогает координировать соглашение о представлении состава участников. Хотя обнаружение сбоев происходит непосредственно посредством связи между силосами, представление членства хранится в надежном хранилище, а механизм управления параллелизмом, предоставляемый этим хранилищем, используется для достижения соглашения о том, кто активен и кто неактивен. В некотором смысле, этот протокол передает решение трудной проблемы распределенного консенсуса на облако. При этом используется полная мощность базовой облачной платформы, используя ее действительно как платформу как услуга (PaaS).Прямая
IAmAliveзапись в таблицу только для диагностикиПомимо сигналов пульсации, отправляемых между силосами, каждый силос также периодически обновляет столбец "Я жив" в своей строке таблицы. Этот столбец "Я жив" используется только для устранения неполадок и диагностики вручную и не используется самим протоколом членства. Обычно он записывается на гораздо более низкой частоте (каждые 5 минут) и служит очень полезным инструментом для системных администраторов, чтобы проверить живость кластера или легко узнать, когда silo был последний живый.
Благодарности
Подтверждения за вклад Алекса Когана в проектирование и реализацию первой версии этого протокола. Эта работа была выполнена в рамках летней стажировки в Microsoft Research в лето 2011 года.
Реализация на базе ZooKeeper IMembershipTable была выполнена Shay Hazor, реализация SQL IMembershipTable выполнена Veikko Eeva, реализация AWS DynamoDB IMembershipTable выполнена Gutemberg Ribeiro, реализация на базе Consul IMembershipTable выполнена Paul North, и, наконец, реализация Apache Cassandra IMembershipTable была адаптирована из OrleansCassandraUtilsArshia001.