Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En esta guía de inicio rápido, usarás Orleans y las API mínimas de ASP.NET Core 8.0 para compilar una aplicación de acortador de direcciones URL. Los usuarios envían una dirección URL completa al punto de conexión /shorten
de la aplicación y reciben una versión acortada que pueden compartir con otros usuarios, que luego se redirigirán al sitio original. La aplicación usa granos y silos de Orleans para administrar el estado de manera distribuida con el fin de permitir escalabilidad y resistencia. Estas características son críticas cuando se desarrollan aplicaciones para servicios de hospedaje en la nube distribuidos, como Azure Container Apps, y plataformas, como Kubernetes.
Al final de la guía de inicio rápido, tendrá una aplicación que crea y controla redireccionamientos usando direcciones URL cortas y fáciles de usar. Aprenderá a:
- Agregar Orleans a una aplicación de ASP.NET Core
- Trabajar con granos y silos.
- Configurar la administración de estados.
- Integrar Orleans con puntos de conexión de API
Requisitos previos
- SDK de .NET 8.0
- Visual Studio 2022 con la carga de trabajo de desarrollo de ASP.NET y web.
Creación de la aplicación
Inicie Visual Studio 2022 y seleccione Crear un proyecto.
En el cuadro de diálogo Crear un proyecto nuevo, seleccione API web de ASP.NET Core y elija Siguiente.
En el cuadro de diálogo Configurar el nuevo proyecto, escriba
OrleansURLShortener
como Nombre del proyecto y seleccione Siguiente.En el cuadro de diálogo Información adicional, selecciona .NET 8.0 (compatibilidad a largo plazo) y desactiva Usar controladores. A continuación, selecciona Crear.
Adición de Orleans al proyecto
Orleans está disponible a través de una colección de paquetes NuGet, cada uno de los cuales proporciona acceso a varias características. Para esta guía de inicio rápido, agregue el paquete NuGet Microsoft.Orleans.Server a la aplicación:
- Haga clic con el botón derecho en el nodo del proyecto OrleansURLShortener en el Explorador de soluciones y seleccione Administrar paquetes NuGet.
- En la ventana Administrador de paquetes, busque Orleans.
- Elija el paquete Microsoft.Orleans.Server en los resultados de la búsqueda y seleccione Instalar.
Abra el archivo Program.cs y reemplace su contenido por el código siguiente:
using Orleans.Runtime;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();
Configuración de los silos
Los silos son un bloque de creación principal de Orleans responsable de almacenar y administrar granos. Un silo puede contener uno o más granos; un grupo de silos se conoce como clúster. Las coordenadas del clúster funcionan entre silos, lo que permite la comunicación con granos como si estuvieran disponibles en un único proceso.
Al principio del archivo Program.cs, refactorice el código para usar Orleans. El siguiente código utiliza una clase ISiloBuilder para crear un clúster localhost con un silo que puede almacenar granos. ISiloBuilder
también utiliza AddMemoryGrainStorage
para configurar los silos de Orleans con el fin de conservar granos en la memoria. En este escenario se usan recursos locales para el desarrollo, pero se puede configurar una aplicación de producción para usar clústeres y almacenamiento altamente escalables con servicios como Azure Blob Storage.
using Orleans.Runtime;
var builder = WebApplication.CreateBuilder(args);
builder.Host.UseOrleans(static siloBuilder =>
{
siloBuilder.UseLocalhostClustering();
siloBuilder.AddMemoryGrainStorage("urls");
});
using var app = builder.Build();
Creación del grano de abreviación de direcciones URL
Los granos son los elementos primitivos más básicos y los bloques de creación de las aplicaciones de Orleans. Un grano es una clase que hereda de la clase base Grain, que administra varios comportamientos internos y puntos de integración con Orleans. Los granos también deben implementar una de las siguientes interfaces para definir su identificador clave de grano. Cada una de estas interfaces define un contrato similar, pero marca la clase con un tipo de datos diferente para el identificador que Orleans usa para hacer un seguimiento del grano, como string o integer.
- IGrainWithGuidKey
- IGrainWithIntegerKey
- IGrainWithStringKey
- IGrainWithGuidCompoundKey
- IGrainWithIntegerCompoundKey
En este tutorial rápido se usa IGrainWithStringKey
, ya que las cadenas son una opción lógica para trabajar con valores de URL y códigos cortos.
Los granos de Orleans también pueden usar una interfaz personalizada para definir sus métodos y propiedades. La interfaz de grano del acortador de direcciones URL debe definir dos métodos:
- Un método
SetUrl
para conservar las direcciones URL originales y acortadas. - Un método
GetUrl
para recuperar la dirección URL original usando la dirección URL acortada.
Anexe la siguiente definición de interfaz al final del archivo Program.cs.
public interface IUrlShortenerGrain : IGrainWithStringKey { Task SetUrl(string fullUrl); Task<string> GetUrl(); }
Cree una clase
UrlShortenerGrain
mediante el código siguiente. Esta clase hereda de la claseGrain
proporcionada por Orleans e implementa la interfazIUrlShortenerGrain
que creó. La clase también usa la interfazIPersistentState
de Orleans para administrar la lectura y escritura de los valores de estado de las direcciones URL en el almacenamiento de silo 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; } = ""; }
Creación de los puntos de conexión
A continuación, cree dos puntos de conexión para usar las configuraciones de grano y silo de Orleans:
- Un punto de conexión
/shorten
para controlar la creación y el almacenamiento de una versión acortada de la dirección URL. La dirección URL original completa se proporciona como un parámetro de cadena de consulta denominadourl
y la dirección URL acortada se devuelve al usuario para usarla más adelante. - Un punto de conexión
/go/{shortenedRouteSegment:required}
para controlar la redirección de los usuarios a la dirección URL original usando la dirección URL acortada que se proporciona como parámetro.
Inserte la interfaz IGrainFactory en los dos puntos de conexión. Las fábricas de granos te permiten recuperar y gestionar referencias a granos individuales almacenados en silos. Anexe el siguiente código al archivo Program.cs antes de la llamada al 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();
Prueba de la aplicación completada
La funcionalidad principal de la aplicación ya está completa y lista para probarse. El código final de la aplicación debe coincidir con el del ejemplo siguiente:
// <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>
Pruebe la aplicación en el explorador siguiendo estos pasos:
Inicie la aplicación con el botón Ejecutar situado en la parte superior de Visual Studio. La aplicación debe iniciarse en el explorador y mostrar el texto
Hello world!
conocido.En la barra de direcciones del explorador, pruebe el punto de conexión
shorten
escribiendo una ruta de dirección URL como{localhost}/shorten?url=https://learn.microsoft.com
. La página debe volver a cargar y proporcionar una dirección URL abreviada. Copie la dirección URL abreviada en el Portapapeles.Pegue la dirección URL abreviada en la barra de direcciones y presione Entrar. La página se debe volver a cargar y redirigirle a https://learn.microsoft.com.