Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Neste início rápido, você usará Orleans e as APIs mínimas do ASP.NET Core 8.0 para criar um aplicativo encurtador de URL. Os usuários enviam uma URL completa para o ponto de extremidade /shorten
do aplicativo e obtêm uma versão abreviada para compartilhar com outras pessoas, que são redirecionadas para o site original. O aplicativo usa Orleans grãos e silos para gerenciar o estado de forma distribuída, permitindo escalabilidade e resiliência. Esses recursos são essenciais ao desenvolver aplicativos para serviços de hospedagem em nuvem distribuída, como Aplicativos de Contêiner do Azure e plataformas como Kubernetes.
No final do início rápido, você tem um aplicativo que cria e manipula redirecionamentos usando URLs curtas e amigáveis. Você aprenderá como:
- Adicionar Orleans a um aplicativo ASP.NET Core
- Trabalhar com grãos e silos
- Configurar o gerenciamento de estado
- Integrar o Orleans com pontos de extremidade de API
Pré-requisitos
- SDK do .NET 8.0
- Visual Studio 2022 com carga de trabalho ASP.NET e desenvolvimento Web
Criar o aplicativo
Inicie o Visual Studio 2022 e selecione Criar um novo projeto.
Na caixa de diálogo Criar um novo projeto, selecione API de Aplicativo Web ASP.NET Core e, em seguida, selecione Avançar.
Na caixa de diálogo Configurar novo projeto, digite
OrleansURLShortener
como Nome do projeto e selecione em Avançar.Na caixa de diálogo Informações adicionais, selecione .NET 8.0 (Suporte de Longo Prazo) e desmarque Usar controladores e, em seguida, selecione Criar.
Adicionar Orleans ao projeto
O Orleans está disponível por meio de uma coleção de pacotes NuGet e cada um deles fornece acesso a vários recursos. Neste início rápido, adicione o pacote NuGet Microsoft.Orleans.Server ao aplicativo:
- Clique com o botão direito do mouse no nó do projeto OrleansURLShortener no gerenciador de soluções e selecione Gerenciar Pacotes NuGet.
- Na janela do gerenciador de pacotes, pesquise Orleans.
- Escolha o pacote Microsoft.Orleans.Server nos resultados da pesquisa e selecione Instalar.
Abra o arquivo Program.cs e substitua o conteúdo existente pelo seguinte código:
using Orleans.Runtime;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Configurar os silos
Os silos são um bloco de construção principal do Orleans responsável por armazenar e gerenciar grãos. Um silo pode conter um ou mais grãos; um grupo de silos é conhecido como um aglomerado. As coordenadas do cluster funcionam entre silos, permitindo a comunicação com grãos como se todos estivessem disponíveis em um único processo.
Na parte superior do arquivo Program.cs, refatore o código para usar o Orleans. O código a seguir usa uma classe ISiloBuilder para criar um cluster localhost com um silo que pode armazenar grãos. O ISiloBuilder
também usa o AddMemoryGrainStorage
para configurar os silos do Orleans a fim de manter granularidades na memória. Este cenário usa recursos locais para desenvolvimento, mas um aplicativo de produção pode ser configurado para usar clusters e armazenamento altamente escalonáveis usando serviços como o Armazenamento de Blob do Azure.
using Orleans.Runtime;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseOrleans(static siloBuilder =>
{
siloBuilder.UseLocalhostClustering();
siloBuilder.AddMemoryGrainStorage("urls");
});
using var app = builder.Build();
Criar o encurtador de URL chamado Grain
Granularidades são os blocos de construção e primitivos mais essenciais de aplicativos do Orleans. Um grain é uma classe que herda da classe base Grain, que gerencia vários comportamentos internos e pontos de integração com Orleans. As granularidades também devem implementar uma das interfaces listadas abaixo para definir o tipo de identificador da chave de granularidade. Cada uma dessas interfaces define um contrato semelhante, mas marca sua classe com um tipo de dados diferente para o identificador que o Orleans usa para rastrear a granularidade, como uma cadeia de caracteres ou inteiro.
- IGrainWithGuidKey
- IGrainWithIntegerKey
- IGrainWithStringKey
- IGrainWithGuidCompoundKey
- IGrainWithIntegerCompoundKey
Neste início rápido, você usará o IGrainWithStringKey
, pois as cadeias de caracteres são uma opção lógica para trabalhar com valores de URL e códigos curtos.
As granularidades do Orleans também podem usar uma interface personalizada para definir seus métodos e propriedades. A interface de granulador de URL deve definir dois métodos:
- Um método
SetUrl
para persistir as URLs originais e suas URLs abreviadas correspondentes. - Um método
GetUrl
para recuperar a URL original usando a URL abreviada.
Anexe a seguinte definição de interface à parte inferior do arquivo Program.cs.
public interface IUrlShortenerGrain : IGrainWithStringKey { Task SetUrl(string fullUrl); Task<string> GetUrl(); }
Crie uma classe
UrlShortenerGrain
usando o código a seguir. Essa classe herda da classeGrain
fornecida por Orleans e implementa a interfaceIUrlShortenerGrain
que você criou. A classe também usa a interfaceIPersistentState
do Orleans para gerenciar a leitura e a gravação de valores de estado para as URLs no silo de armazenamento configurado.public sealed class UrlShortenerGrain( [PersistentState( stateName: "url", storageName: "urls")] IPersistentState<UrlDetails> state) : Grain, IUrlShortenerGrain { public async Task SetUrl(string fullUrl) { state.State = new() { ShortenedRouteSegment = this.GetPrimaryKeyString(), FullUrl = fullUrl }; await state.WriteStateAsync(); } public Task<string> GetUrl() => Task.FromResult(state.State.FullUrl); } [GenerateSerializer, Alias(nameof(UrlDetails))] public sealed record class UrlDetails { [Id(0)] public string FullUrl { get; set; } = ""; [Id(1)] public string ShortenedRouteSegment { get; set; } = ""; }
Criar os pontos de extremidade
Em seguida, crie dois pontos de extremidade para utilizar as configurações de granularidade e silo do Orleans:
- Um ponto de extremidade
/shorten
para lidar com a criação e o armazenamento de uma versão abreviada da URL. A URL original completa é fornecida como um parâmetro de cadeia de caracteres de consulta chamadourl
e a URL abreviada é retornada ao usuário para uso posterior. - Um endpoint
/go/{shortenedRouteSegment:required}
para lidar com o redirecionamento de usuários para a URL original usando a URL encurtada fornecida como parâmetro.
Injete a interface IGrainFactory em ambos os pontos de extremidade. As Fábricas de Grãos permitem que você recupere e gerencie referências a grãos individuais armazenados em silos. Anexe o seguinte código ao arquivo Program.cs antes da chamada do método app.Run()
:
app.MapGet("/", static () => "Welcome to the URL shortener, powered by Orleans!");
app.MapGet("/shorten",
static async (IGrainFactory grains, HttpRequest request, string url) =>
{
var host = $"{request.Scheme}://{request.Host.Value}";
// Validate the URL query string.
if (string.IsNullOrWhiteSpace(url) ||
Uri.IsWellFormedUriString(url, UriKind.Absolute) is false)
{
return Results.BadRequest($"""
The URL query string is required and needs to be well formed.
Consider, ${host}/shorten?url=https://www.microsoft.com.
""");
}
// Create a unique, short ID
var shortenedRouteSegment = Guid.NewGuid().GetHashCode().ToString("X");
// Create and persist a grain with the shortened ID and full URL
var shortenerGrain =
grains.GetGrain<IUrlShortenerGrain>(shortenedRouteSegment);
await shortenerGrain.SetUrl(url);
// Return the shortened URL for later use
var resultBuilder = new UriBuilder(host)
{
Path = $"/go/{shortenedRouteSegment}"
};
return Results.Ok(resultBuilder.Uri);
});
app.MapGet("/go/{shortenedRouteSegment:required}",
static async (IGrainFactory grains, string shortenedRouteSegment) =>
{
// Retrieve the grain using the shortened ID and url to the original URL
var shortenerGrain =
grains.GetGrain<IUrlShortenerGrain>(shortenedRouteSegment);
var url = await shortenerGrain.GetUrl();
// Handles missing schemes, defaults to "http://".
var redirectBuilder = new UriBuilder(url);
return Results.Redirect(redirectBuilder.Uri.ToString());
});
app.Run();
Teste o aplicativo finalizado
A funcionalidade principal do aplicativo agora está completa e pronta para ser testada. O código final do aplicativo deve corresponder ao seguinte exemplo:
// <configuration>
using Orleans.Runtime;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseOrleans(static siloBuilder =>
{
siloBuilder.UseLocalhostClustering();
siloBuilder.AddMemoryGrainStorage("urls");
});
using var app = builder.Build();
// </configuration>
// <endpoints>
app.MapGet("/", static () => "Welcome to the URL shortener, powered by Orleans!");
app.MapGet("/shorten",
static async (IGrainFactory grains, HttpRequest request, string url) =>
{
var host = $"{request.Scheme}://{request.Host.Value}";
// Validate the URL query string.
if (string.IsNullOrWhiteSpace(url) ||
Uri.IsWellFormedUriString(url, UriKind.Absolute) is false)
{
return Results.BadRequest($"""
The URL query string is required and needs to be well formed.
Consider, ${host}/shorten?url=https://www.microsoft.com.
""");
}
// Create a unique, short ID
var shortenedRouteSegment = Guid.NewGuid().GetHashCode().ToString("X");
// Create and persist a grain with the shortened ID and full URL
var shortenerGrain =
grains.GetGrain<IUrlShortenerGrain>(shortenedRouteSegment);
await shortenerGrain.SetUrl(url);
// Return the shortened URL for later use
var resultBuilder = new UriBuilder(host)
{
Path = $"/go/{shortenedRouteSegment}"
};
return Results.Ok(resultBuilder.Uri);
});
app.MapGet("/go/{shortenedRouteSegment:required}",
static async (IGrainFactory grains, string shortenedRouteSegment) =>
{
// Retrieve the grain using the shortened ID and url to the original URL
var shortenerGrain =
grains.GetGrain<IUrlShortenerGrain>(shortenedRouteSegment);
var url = await shortenerGrain.GetUrl();
// Handles missing schemes, defaults to "http://".
var redirectBuilder = new UriBuilder(url);
return Results.Redirect(redirectBuilder.Uri.ToString());
});
app.Run();
// </endpoints>
// <graininterface>
public interface IUrlShortenerGrain : IGrainWithStringKey
{
Task SetUrl(string fullUrl);
Task<string> GetUrl();
}
// </graininterface>
// <grain>
public sealed class UrlShortenerGrain(
[PersistentState(
stateName: "url",
storageName: "urls")]
IPersistentState<UrlDetails> state)
: Grain, IUrlShortenerGrain
{
public async Task SetUrl(string fullUrl)
{
state.State = new()
{
ShortenedRouteSegment = this.GetPrimaryKeyString(),
FullUrl = fullUrl
};
await state.WriteStateAsync();
}
public Task<string> GetUrl() =>
Task.FromResult(state.State.FullUrl);
}
[GenerateSerializer, Alias(nameof(UrlDetails))]
public sealed record class UrlDetails
{
[Id(0)]
public string FullUrl { get; set; } = "";
[Id(1)]
public string ShortenedRouteSegment { get; set; } = "";
}
// </grain>
Teste o aplicativo no navegador usando as seguintes etapas:
Inicie o aplicativo usando o botão executar na parte superior do Visual Studio. O aplicativo deve ser iniciado no navegador e exibir o texto familiar
Hello world!
.Na barra de endereços do navegador, teste o endpoint
shorten
inserindo um caminho de URL, como{localhost}/shorten?url=https://learn.microsoft.com
. A página deve recarregar e fornecer uma URL abreviada. Copie a URL abreviada para sua área de transferência.Cole a URL abreviada na barra de endereços e pressione Enter. A página deve recarregar e redirecionar você para https://learn.microsoft.com.