Распределенная среда Orleans Microsoft на основе акторов

1. Принцип работы акторной модели

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

Основной принцип работы модели Актера заключается в следующем:
1. Каждый Актер имеет уникальный идентификатор и может получать и отправлять сообщения.
2. Актеры взаимодействуют посредством передачи сообщений, и у каждого Актера есть очередь сообщений для хранения полученных сообщений.
3. Актеры могут выполнять некоторые локальные операции, но не могут напрямую обращаться к состоянию других акторов. Если он хочет получить доступ к состоянию других акторов, он должен запрашивать данные у других акторов, отправляя сообщения.
4. Когда актор получает сообщение, он выполняет соответствующие операции в соответствии с логикой обработки сообщения и может отправлять сообщения другим акторам.
5. Связь между Актерами является асинхронной, то есть Актеру, отправляющему сообщение, не нужно ждать, пока Актер, получивший сообщение, закончит обработку сообщения, прежде чем продолжить выполнение.
6. В модели «Актор» все операции реализованы на основе передачи сообщений, что позволяет избежать проблем параллелизма, таких как условия гонки и тупиковые ситуации.

Как работает актерская модель

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

2. Знакомство с Орлеаном

        Orleans — это распределенная среда моделирования на основе акторов с открытым исходным кодом от Microsoft.

        Orleans — это кроссплатформенная платформа для создания надежных и масштабируемых распределенных приложений. Распределенное приложение определяется как приложение, охватывающее несколько процессов, часто использующее одноранговую связь для преодоления аппаратных ограничений. Orleans масштабируется от одного локального сервера до сотен тысяч распределенных высокодоступных приложений в облаке. Orleans расширяет знакомые концепции и идиомы C# на многосерверные среды. Орлеан эластично масштабируется по своему дизайну. Когда хост присоединяется к кластеру, он может принимать новые активации. Когда узел покидает кластер из-за масштабирования или сбоя компьютера, предыдущие активации на этом узле повторно активируются на оставшихся узлах по мере необходимости. Кластеры Orleans можно масштабировать до одного хоста. Те же свойства, которые используются для обеспечения гибкого масштабирования, также обеспечивают отказоустойчивость. Кластер автоматически обнаруживает сбои и быстро восстанавливается после них.

        Одной из основных целей проектирования Orleans было упростить разработку распределенных приложений за счет предоставления общего набора шаблонов и API-интерфейсов. Разработчики, знакомые с разработкой приложений для одного сервера, могут легко переключиться на использование Orleans для создания отказоустойчивых, масштабируемых облачных сервисов и других распределенных приложений. По этой причине Orleans часто называют «распределенной .NET», и он является предпочтительным фреймворком для создания облачных приложений.

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

        Метод, принятый Орлеаном, заключается в использовании принципа модели Актера для разработки класса, чтобы гарантировать, что процесс выполнения этого класса от процесса «создания» до процесса «уничтожения», а также «метод, который вызывает его на полпути». Эти три «процесса» будут выполняться в одном потоке независимо от того, когда и где они вызываются. Таким образом, я могу смело изменять и вызывать метод этого класса, не беспокоясь о «грязном чтении» переменной, указывающей на этот класс.

        В модели Орлеана у каждого Актера есть специальный класс для его представления, называемый Зерно, и этот класс зерна является «человеком» в моделируемой сцене общения.

1. Что такое зерно

        Зерно — один из нескольких орлеанских примитивов. Что касается акторной модели, зерно — это виртуальный актор. Основным строительным блоком любого приложения Orleans является гранула. Зерно — это сущность с определяемой пользователем идентичностью, поведением и состоянием. Рассмотрим следующее визуальное представление зерна:

 

        Идентификаторы зерна — это определяемые пользователем ключи, доступные в нескольких типах, что делает зерно всегда доступным для вызова. Зерна могут содержать изменчивые или постоянные данные о состоянии, которые можно хранить в любой системе хранения. Таким образом, гранулы неявно разделяют состояние приложения, обеспечивая автоматическую масштабируемость и упрощая восстановление после сбоев. Когда гранула активна, ее состояние сохраняется в памяти, что снижает задержку и разгружает хранилище данных.

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

        Чтобы решить проблемы «конкуренции ресурсов», вызванные многопоточностью, Orleans гарантирует, что каждый класс зерна соответствует следующим спецификациям поведения в рамках Orleans framework:

  А.Любые сообщения, отправленные в один и тот же экземпляр класса зерна, будут выполняться в фиксированном потоке.
  Б. Класс зерна обрабатывает сообщения последовательно в соответствии с порядком их получения. В любой момент времени экземпляр зерна обрабатывает только одно сообщение.
  С.Свойство поля внутри экземпляра зерна, доступ к которому может получить только сам экземпляр. Внешний мир не может получить к нему доступ.

 2. Что такое бункер?

        Бункер — еще один пример орлеанского примитива. Силос содержит одно или несколько зерен. Среда выполнения Orleans реализует модель программирования для приложений.

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

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

В дополнение к базовой модели программирования разрозненные хранилища предоставляют зернам набор служб времени выполнения, таких как таймеры, напоминания (постоянные таймеры), постоянство, транзакции, потоки и многое другое.

3. Что можно сделать с Орлеаном

        Orleans — это платформа для создания облачных приложений. Всякий раз, когда вы создаете приложения .NET, которые в конечном итоге необходимо масштабировать, рассмотрите возможность использования Orleans. Варианты использования Orleans могут показаться бесчисленными, но вот некоторые из наиболее распространенных: игры, банковские операции, приложения для чата, GPS-отслеживание, торговля акциями, тележки для покупок, приложения для голосования и многое другое. Microsoft использует Orleans в Azure, Xbox, Skype, Halo, PlayFab, Gears of War и многих других внутренних службах. Многие функции Orleans упрощают использование в различных приложениях.

 3. Простой пример использования Orleans

Создайте проект для реализации простого средства сокращения URL-адресов с помощью Grain.

#创建新web项目
dotnet new web -o UrlShortener -f net7.0

#进入项目文件夹,打开编辑器
cd UrlShortener
code .

 Добавьте компонент orleans в проект

#将 Orleans 添加到项目
dotnet add package Microsoft.Orleans.Server -v 7.0.0

Добавьте ссылку на заголовок файла program.cs

using Microsoft.AspNetCore.Http.Extensions;
using Orleans.Runtime;

1. Создайте класс зерна

        Во-первых, в нижней части файла program.cs добавьте интерфейс, унаследованный от IGrainWithStringKey, для реализации настройки и чтения.

public interface IUrlShortenerGrain : IGrainWithStringKey
{
    Task SetUrl(string shortenedRouteSegment, string fullUrl);
    Task<string> GetUrl();
}

Затем создайте класс UrlShortenerGrain и реализуйте этот интерфейс.

public class UrlShortenerGrain : Grain, IUrlShortenerGrain
{
    private KeyValuePair<string, string> _cache;

    public Task SetUrl(string shortenedRouteSegment, string fullUrl)
    {
        _cache = new KeyValuePair<string, string>(shortenedRouteSegment, fullUrl);
        return Task.CompletedTask;
    }

    public Task<string?> GetUrl()
    {
        return Task.FromResult(_cache.Value);
    }
}

2. Создайте и настройте приемник 

В верхней части класса Program выполните рефакторинг кода построителя для использования Orleans. Завершенный код должен выглядеть, как в следующем примере:

var builder = WebApplication.CreateBuilder();

builder.Host.UseOrleans(siloBuilder =>
{
    siloBuilder.UseLocalhostClustering();
});

var app = builder.Build();

        Затем необходимо получить экземпляр гранулярной фабрики. Orleans предоставляет фабрику зерна по умолчанию, которая управляет созданием и извлечением зерна с использованием идентификатора зерна. После вызова var app = builder.Build(); добавьте следующую строку кода, чтобы получить фабрику зерна и сохранить ее в переменной с именем GrainFactory:

var grainFactory = app.Services.GetRequiredService<IGrainFactory>();

3. Создайте маршрут получения длинного URL-адреса

Измените код, который изначально выводил «Hello, world», чтобы он принимал длинные URL-адреса и готовился возвращать короткие URL-адреса.

app.MapGet("/shorten/{*path}",
    async (IGrainFactory grains, HttpRequest request, string path) =>
{
    return Results.Ok();
});

В настоящее время возвращается нулевое значение 200, и оно улучшено для возврата короткого пути URL.

app.MapGet("/shorten/{*path}",
async (IGrainFactory grains, HttpRequest request, string path) =>
{
    var shortenedRouteSegment = Guid.NewGuid().GetHashCode().ToString("X");
    var shortenerGrain = grains.GetGrain<IUrlShortenerGrain>(shortenedRouteSegment);
    await shortenerGrain.SetUrl(shortenedRouteSegment, path);
    var resultBuilder = new UriBuilder(request.GetEncodedUrl())
    {
        Path = $"/go/{shortenedRouteSegment}"
    };

    return Results.Ok(resultBuilder.Uri);
});

Приведенный выше код выполняет несколько задач:

  • Во-первых, GUID используется для создания случайного укороченного сегмента маршрута из его хэш-кода в виде шестнадцатеричной строки.
  • Затем фабрика гранул использует укороченный сегмент маршрута в качестве идентификатора для создания новой гранулы.
  • Детальные экземпляры хранят укороченные сегменты маршрута и исходные URL-адреса назначения, чтобы их можно было получить позже.
  • Наконец, новый URL-адрес, содержащий сокращенный сегмент маршрута, собирается и возвращается пользователю.

4. Создайте путь маршрутизации, который перенаправляет на соответствующий длинный URL-адрес при доступе к короткому URL-адресу.

app.MapGet("/go/{shortenedRouteSegment}",
    async (IGrainFactory grains, string shortenedRouteSegment) =>
{
    var shortenerGrain = grains.GetGrain<IUrlShortenerGrain>(shortenedRouteSegment);
    var url = await shortenerGrain.GetUrl();

    return Results.Redirect(url);
});

Этот код выполняет следующие задачи для обработки запроса пользователя.

  • Извлекает зерно, содержащее информацию о перенаправлении для предоставленного короткого URL-адреса, из фабрики зерна, используя имя короткого URL-адреса в качестве ключа.
  • Извлекает полную строку URL из зерна.
  • Если соответствующий URL-адрес найден, пользователь перенаправляется туда, в противном случае возвращается 404.

5. Запустите тест

dotnet run

 Например, посетите {localhost}/shorten/https://blog.csdn.net/zhujisoft и получите короткий путь «http://localhost:5205/go/AB39050D».

Получите доступ к короткому пути http://localhost:5205/go/AB39050D, затем вы можете перенаправить на длинный URL-адрес и использовать зернистость для реализации простой функции преобразования.

 6. Сохраняйте состояние, попробуйте сохранить данные с зерном

Объекты для сохранения состояния можно определить, объявив их в конструкторе зерна и украсив их атрибутом PersistentState. Объекты, украшенные этим атрибутом, имеют доступ к методам API, описанным ранее.
Свойство PersistentState принимает два параметра:

  • Имя: определяет имя объекта состояния.
  • StorageName: определяет поставщика хранилища, в котором должен быть сохранен объект.
public class UrlShortenerGrain : Grain, IUrlShortenerGrain
{
    private readonly IPersistentState<KeyValuePair<string, string>> _cache;

    public UrlShortenerGrain(
        [PersistentState(
            stateName: "url",
            storageName: "urls")]
            IPersistentState<KeyValuePair<string, string>> state)
    {
        _cache = state;
    }
}

7. Настройте способ хранения зерна

builder.Host.UseOrleans(siloBuilder =>
{
    siloBuilder.UseLocalhostClustering();
    siloBuilder.AddAzureBlobGrainStorage("urls",
        // Recommended: Connect to Blob Storage using DefaultAzureCredential
        options =>
        {
            options.ConfigureBlobServiceClient(new Uri("https://<your-account-name>.blob.core.windows.net"),
                new DefaultAzureCredential());
        });
        // Connect to Blob Storage using Connection strings
        // options => options.ConfigureBlobServiceClient(connectionString));
});

         Примеры поставщиков хранилищ включают традиционные базы данных SQL, различные службы Azure, такие как хранилище BLOB-объектов, и другие облачные ресурсы, такие как Amazon DynamoDb. Эти поставщики доступны через различные пакеты NuGet. Orleans также предоставляет точки расширения для добавления собственных поставщиков хранилищ.

Для простоты в этом примере используется хранилище в памяти.

builder.Host.UseOrleans(siloBuilder =>
{
    siloBuilder.UseLocalhostClustering();
    siloBuilder.AddMemoryGrainStorage("urls");
});

Обновите конструктор зерна и использование

public async Task SetUrl(string shortenedRouteSegment, string fullUrl)
{
    _cache.State = new KeyValuePair<string, string>(shortenedRouteSegment, fullUrl);
    await _cache.WriteStateAsync();
}

public Task<string> GetUrl()
{
    return Task.FromResult(_cache.State.Value);
}

С тех пор приложение теперь поддерживает постоянное состояние.

4. Справочные статьи

1. Введение в Orleans-Training | Microsoft Learn

2. Введение-обучение | Microsoft Learn

3. Принцип работы акторной модели — официальный сайт Tengke IT Education.

4. Введение в Orleans_c# orleans framework component_liyan530's blog-CSDN blog

Supongo que te gusta

Origin blog.csdn.net/zhujisoft/article/details/131716423
Recomendado
Clasificación