Configuración del servidor
Un silo se configura mediante programación con el método de extensión UseOrleans(IHostBuilder, Action<HostBuilderContext,ISiloBuilder>) y varias clases de opciones complementarias. Las clases de opciones de Orleans siguen el Patrón de opciones de .NET y pueden cargarse mediante archivos, variables de entorno o cualquier otro proveedor de configuración válido.
Hay varios aspectos clave de la configuración del silo:
- Proveedor de la agrupación en clústeres
- (Opcional) Información de la agrupación en clústeres de Orleans
- (Opcional) Puntos de conexión que se usarán para las comunicaciones de silo a silo y de cliente a silo
Este es un ejemplo de una configuración de silo que define la información del clúster, usa la agrupación en clústeres de Azure y configura los elementos de la aplicación:
using IHost host = Host.CreateDefaultBuilder(args)
.UseOrleans(builder =>
{
builder.UseAzureStorageClustering(
options => options.ConfigureTableServiceClient(connectionString));
})
.UseConsoleLifetime()
.Build();
Sugerencia
Al desarrollar para Orleans, puede llamar a UseLocalhostClustering(ISiloBuilder, Int32, Int32, IPEndPoint, String, String) para configurar un clúster local. En entornos de producción, debe usar un proveedor de agrupación en clústeres adecuado para la implementación en cuestión.
Proveedor de la agrupación en clústeres
siloBuilder.UseAzureStorageClustering(
options => options.ConfigureTableServiceClient(connectionString))
Por lo general, un servicio basado en Orleans se implementa en un clúster de nodos, ya sea en hardware dedicado o en la nube. Para el desarrollo y las pruebas básicas, Orleans se puede implementar en una configuración de nodo único. Cuando se implementa en un clúster de nodos, Orleans implementa internamente un conjunto de protocolos para detectar y mantener la pertenencia a silos de Orleans en el clúster, incluida la detección de errores de nodo y la reconfiguración automática.
Para una administración confiable de la pertenencia a clústeres, Orleans usa Azure Table, SQL Server o Apache ZooKeeper para la sincronización de nodos.
En este ejemplo, se usa Azure Table como proveedor de pertenencia.
Información de la agrupación en clústeres de Orleans
Para configurar opcionalmente la agrupación en clústeres, use ClusterOptions
como parámetro de tipo para el método Configure en la instancia de ISiloBuilder
.
siloBuilder.Configure<ClusterOptions>(options =>
{
options.ClusterId = "my-first-cluster";
options.ServiceId = "SampleApp";
})
Aquí se especifican dos opciones:
- Establecer
ClusterId
en"my-first-cluster"
: se trata de un identificador único para el clúster de Orleans. Todos los clientes y silos que usan este Id. podrán comunicarse directamente entre sí. Sin embargo, puede optar por usar otroClusterId
para diferentes implementaciones. - Establezca
ServiceId
en"SampleApp"
: se trata de un Id. único para la aplicación que usarán algunos proveedores, como los proveedores de persistencia. Este Id. debería permanecer estable y no cambiar entre implementaciones.
De manera predeterminada, Orleans usará un valor de "default"
para ServiceId
y ClusterId
. En la mayoría de los casos, no es necesario cambiar estos valores. ServiceId
es el más significativo de los dos y se utiliza para distinguir los distintos servicios lógicos para que puedan compartir sistemas de almacenamiento back-end sin interferir entre sí. ClusterId
se usa para determinar los hosts que se conectarán entre sí y formarán un clúster.
Dentro de cada clúster, todos los hosts deben usar el mismo ServiceId
. Sin embargo, varios clústeres pueden compartir un ServiceId
. Esto permite escenarios de implementación azul-verde en los que se inicia una implementación nueva (clúster) antes de apagar otra. Esto es típico para los sistemas que se hospedan en Azure App Service.
El caso más común es que ServiceId
y ClusterId
permanecen fijos durante la vigencia de la aplicación y se usa una estrategia de implementación gradual. Esto es típico para los sistemas que se hospedan en Kubernetes y Service Fabric.
Puntos de conexión
De manera predeterminada, Orleans escuchará en todas las interfaces en el puerto 11111
para la comunicación de silo a silo y en el puerto 30000
para la comunicación de cliente a silo. Para reemplazar este comportamiento, llame a ConfigureEndpoints(ISiloBuilder, Int32, Int32, AddressFamily, Boolean) y pase los números de puerto que desea usar.
siloBuilder.ConfigureEndpoints(siloPort: 17_256, gatewayPort: 34_512)
En el código anterior:
- El puerto de silo se establece en
17_256
. - El puerto de puerta de enlace se establece en
34_512
.
Un silo de Orleans tiene dos tipos típicos de configuración de punto de conexión:
- Los puntos de conexión de silo a silo se usan para la comunicación entre silos en el mismo clúster.
- Los puntos de conexión de cliente a silo (o puerta de enlace) se usan para la comunicación entre clientes y silos en el mismo clúster.
Este método debe ser suficiente en la mayoría de los casos, pero puede personalizarlo aún más si es necesario. Este es un ejemplo de cómo usar una dirección IP externa con reenvío de puertos:
siloBuilder.Configure<EndpointOptions>(options =>
{
// Port to use for silo-to-silo
options.SiloPort = 11_111;
// Port to use for the gateway
options.GatewayPort = 30_000;
// IP Address to advertise in the cluster
options.AdvertisedIPAddress = IPAddress.Parse("172.16.0.42");
// The socket used for client-to-silo will bind to this endpoint
options.GatewayListeningEndpoint = new IPEndPoint(IPAddress.Any, 40_000);
// The socket used by the gateway will bind to this endpoint
options.SiloListeningEndpoint = new IPEndPoint(IPAddress.Any, 50_000);
})
Internamente, el silo escuchará en 0.0.0.0:40000
y 0.0.0.0:50000
, pero el valor publicado en el proveedor de pertenencia será 172.16.0.42:11111
y 172.16.0.42:30000
.
Un silo se configura mediante programación a través de SiloHostBuilder y de varias clases de opciones complementarias. Las clases de opciones de Orleans siguen el Patrón de opciones de .NET y pueden cargarse mediante archivos, variables de entorno o cualquier otro proveedor de configuración válido.
Hay varios aspectos clave de la configuración del silo:
- Información de la agrupación en clústeres de Orleans
- Proveedor de la agrupación en clústeres
- Puntos de conexión que se usarán para las comunicaciones de silo a silo y de cliente a silo
- Elementos de la aplicación
Este es un ejemplo de una configuración de silo que define la información del clúster, usa la agrupación en clústeres de Azure y configura los elementos de la aplicación:
var silo = Host.CreateDefaultBuilder(args)
.UseOrleans(builder =>
{
builder
.UseAzureStorageClustering(
options => options.ConnectionString = connectionString)
.Configure<ClusterOptions>(options =>
{
options.ClusterId = "my-first-cluster";
options.ServiceId = "AspNetSampleApp";
})
.ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000)
.ConfigureApplicationParts(
parts => parts.AddApplicationPart(typeof(ValueGrain).Assembly).WithReferences())
})
.UseConsoleLifetime()
.Build();
Vamos a desglosar los pasos que se usan en este ejemplo:
Proveedor de la agrupación en clústeres
siloBuilder.UseAzureStorageClustering(
options => options.ConnectionString = connectionString)
Por lo general, un servicio basado en Orleans se implementa en un clúster de nodos, ya sea en hardware dedicado o en la nube. Para el desarrollo y las pruebas básicas, Orleans se puede implementar en una configuración de nodo único. Cuando se implementa en un clúster de nodos, Orleans implementa internamente un conjunto de protocolos para detectar y mantener la pertenencia a silos de Orleans en el clúster, incluida la detección de errores de nodo y la reconfiguración automática.
Para una administración confiable de la pertenencia a clústeres, Orleans usa Azure Table, SQL Server o Apache ZooKeeper para la sincronización de nodos.
En este ejemplo, usamos Azure Table como proveedor de pertenencia.
Información de la agrupación en clústeres de Orleans
.Configure<ClusterOptions>(options =>
{
options.ClusterId = "my-first-cluster";
options.ServiceId = "AspNetSampleApp";
})
Aquí hacemos dos cosas:
- Establecer
ClusterId
en"my-first-cluster"
: se trata de un identificador único para el clúster de Orleans. Todos los clientes y silos que usan este Id. podrán comunicarse directamente entre sí. Sin embargo, puede optar por usar otroClusterId
para diferentes implementaciones. - Establezca
ServiceId
en"AspNetSampleApp"
: se trata de un Id. único para la aplicación que usarán algunos proveedores, como los proveedores de persistencia. Este Id. debería permanecer estable y no cambiar entre implementaciones.
De manera predeterminada, Orleans usará un valor de "default"
para ServiceId
y ClusterId
. En la mayoría de los casos, no es necesario cambiar estos valores. ServiceId
es el más significativo de los dos y se utiliza para distinguir los distintos servicios lógicos para que puedan compartir sistemas de almacenamiento back-end sin interferir entre sí. ClusterId
se usa para determinar los hosts que se conectarán entre sí y formarán un clúster.
Dentro de cada clúster, todos los hosts deben usar el mismo ServiceId
. Sin embargo, varios clústeres pueden compartir un ServiceId
. Esto permite escenarios de implementación azul-verde en los que se inicia una implementación nueva (clúster) antes de apagar otra. Esto es típico para los sistemas que se hospedan en Azure App Service.
El caso más común es que ServiceId
y ClusterId
permanecen fijos durante la vigencia de la aplicación y se usa una estrategia de implementación gradual. Esto es típico para los sistemas que se hospedan en Kubernetes y Service Fabric.
Puntos de conexión
siloBuilder.ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000)
Un silo de Orleans tiene dos tipos típicos de configuración de punto de conexión:
- Puntos de conexión de silo a silo, que se usan para la comunicación entre silos en el mismo clúster
- Puntos de conexión de cliente a silo (o puerta de enlace), que se usan para la comunicación entre clientes y silos en el mismo clúster
En el ejemplo, se usa el método auxiliar .ConfigureEndpoints(siloPort: 11111, gatewayPort: 30000)
, que establece el puerto usado para la comunicación de silo a silo en 11111
y el puerto de la puerta de enlace en 30000
.
Este método detectará la interfaz que hay que escuchar.
Este método debe ser suficiente en la mayoría de los casos, pero puede personalizarlo aún más si es necesario. Este es un ejemplo de cómo usar una dirección IP externa con reenvío de puertos:
siloBuilder.Configure<EndpointOptions>(options =>
{
// Port to use for silo-to-silo
options.SiloPort = 11111;
// Port to use for the gateway
options.GatewayPort = 30000;
// IP Address to advertise in the cluster
options.AdvertisedIPAddress = IPAddress.Parse("172.16.0.42");
// The socket used for client-to-silo will bind to this endpoint
options.GatewayListeningEndpoint = new IPEndPoint(IPAddress.Any, 40000);
// The socket used by the gateway will bind to this endpoint
options.SiloListeningEndpoint = new IPEndPoint(IPAddress.Any, 50000);
})
Internamente, el silo escuchará en 0.0.0.0:40000
y 0.0.0.0:50000
, pero el valor publicado en el proveedor de pertenencia será 172.16.0.42:11111
y 172.16.0.42:30000
.
Elementos de la aplicación
siloBuilder.ConfigureApplicationParts(
parts => parts.AddApplicationPart(
typeof(ValueGrain).Assembly)
.WithReferences())
Aunque este paso no es técnicamente necesario (si no está configurado, Orleans examinará todos los ensamblados de la carpeta actual), se recomienda a los desarrolladores que lo configuren. Este paso ayudará a Orleans a cargar los ensamblados y tipos de usuario. Estos ensamblados se conocen como Elementos de la aplicación. Todos los Granos, Interfaces de granos y Serializadores se detectan mediante Elementos de la aplicación.
Los Elementos de la aplicación se configuran mediante IApplicationPartManager, al que se puede tener acceso mediante el método de extensión ConfigureApplicationParts
en IClientBuilder y ISiloHostBuilder. El método ConfigureApplicationParts
acepta un delegado, Action<IApplicationPartManager>
.
Los métodos de extensión siguientes en IApplicationPartManager admiten usos comunes:
- ApplicationPartManagerExtensions.AddApplicationPart: con este método de extensión, se puede agregar un ensamblado único.
- ApplicationPartManagerExtensions.AddFromAppDomain agrega todos los ensamblados cargados actualmente en
AppDomain
. - ApplicationPartManagerExtensions.AddFromApplicationBaseDirectory carga y agrega todos los ensamblados en la ruta de acceso base actual (consulte AppDomain.BaseDirectory).
Los ensamblados agregados por los métodos anteriores se pueden complementar mediante los métodos de extensión siguientes en su tipo de valor devuelto, IApplicationPartManagerWithAssemblies:
- ApplicationPartManagerExtensions.WithReferences agrega todos los ensamblados de las partes agregadas a los que se hace referencia. Esto carga inmediatamente los ensamblados a los que se hace referencia transitivamente. Los errores de carga de los ensamblados se omiten.
- ApplicationPartManagerCodeGenExtensions.WithCodeGeneration genera código de compatibilidad para los elementos agregados y lo agrega al administrador de elementos. Tenga en cuenta que esto requiere que se instale el paquete
Microsoft.Orleans.OrleansCodeGenerator
y se conoce normalmente como generación de código en tiempo de ejecución.
La detección de tipos requiere que los Elementos de aplicación proporcionados incluyan atributos específicos. Agregar el paquete de generación de código en tiempo de compilación (Microsoft.Orleans.CodeGenerator.MSBuild
o Microsoft.Orleans.OrleansCodeGenerator.Build
) a cada proyecto que contiene Granos, Interfaces de granos o Serializadores es el enfoque recomendado para asegurarse de que estos atributos están presentes. La generación de código en tiempo de compilación solo admite C#. En el caso de F#, Visual Basic y otros lenguajes de .NET, el código se puede generar durante el tiempo de configuración mediante el método WithCodeGeneration descrito anteriormente. Puede encontrar más información sobre la generación de código en la sección correspondiente.