Colocación de granos
Orleans garantiza que cuando se realiza una llamada de grano hay una instancia de ese grano disponible en memoria en algún servidor del clúster para controlar la solicitud. Si el grano no está activo actualmente en el clúster, Orleans elige uno de los servidores para que el grano se active allí. Esto se denomina colocación del grano. La colocación también es una forma de equilibrar la carga: incluso la colocación de granos que ya tienen actividad ayuda a repartir equitativamente la carga de trabajo en todo el clúster.
El proceso de colocación en Orleans es completamente configurable: los desarrolladores pueden elegir entre un conjunto de directivas de colocación predeterminadas, por ejemplo, aleatoria, con prioridad para el entorno local o en función de la carga. También pueden configurar una lógica personalizada. Esto permite una flexibilidad completa para decidir dónde se crean los granos. Por ejemplo, los granos se pueden colocar en un servidor cerca de los recursos en los que necesitan operar o cerca de otros granos con los que se comunican. De forma predeterminada, Orleans elegirá un servidor compatible aleatoriamente.
La estrategia de ubicación que Orleans usa se puede configurar globalmente o por clase de grano.
Colocación aleatoria
Un servidor se selecciona aleatoriamente de los servidores compatibles del clúster. Esta estrategia de colocación se configura agregando RandomPlacementAttribute a un grano.
Ubicación local
Si el servidor local es compatible, seleccione el servidor local; de lo contrario, seleccione un servidor aleatorio. Esta estrategia de colocación se configura agregando PreferLocalPlacementAttribute a un grano.
Colocación en función del hash
Aplique un hash del identificador de grano a un entero no negativo y calcule su módulo con el número de servidores compatibles. Seleccione el servidor correspondiente en la lista de servidores compatibles ordenados por dirección del servidor. Tenga en cuenta que esto no se garantiza que permanezca estable a medida que cambia la pertenencia al clúster. En concreto, agregar, quitar o reiniciar servidores puede modificar el servidor seleccionado para un grain id determinado. Dado que los granos colocados con esta estrategia se registran en el directorio de granos, este cambio en la decisión de ubicación debido a cambios en la membresía normalmente no tiene un efecto notable.
Esta estrategia de colocación se configura agregando HashBasedPlacementAttribute a un grano.
Colocación en función del recuento de activación
Esta estrategia de selección de ubicación pretende colocar nuevas activaciones de granos en el servidor menos cargado en función del número de granos ocupados recientemente. Incluye un mecanismo en el que todos los servidores publican periódicamente su recuento total de activación en todos los demás servidores. A continuación, el director de selección de ubicación selecciona un servidor que se predice que tiene las menos activaciones examinando el recuento de activación notificado más recientemente y predice el recuento de activación actual en función del recuento de activación reciente realizado por el director de selección de ubicación en el servidor actual. El director selecciona varios servidores de forma aleatoria al realizar esta predicción para evitar que varios servidores independientes sobrecarguen el mismo servidor. De forma predeterminada, se seleccionan dos servidores aleatoriamente, pero este valor se puede configurar a través de ActivationCountBasedPlacementOptions.
Este algoritmo se basa en la tesis "El Poder de Dos Opciones en el Balanceo de Carga Aleatorio" de Michael David Mitzenmacher, y también se usa en Nginx para el equilibrio de carga distribuido, como se describe en el artículo "NGINX y el Algoritmo de 'El Poder de Dos Opciones'" Load-Balancing.
Esta estrategia de colocación se configura agregando ActivationCountBasedPlacementAttribute a un grano.
Asignación de trabajadores sin estado
La colocación de trabajos sin estado es una estrategia especial de colocación que utilizan los granos de trabajo sin estado. Esta colocación funciona casi de forma idéntica a PreferLocalPlacement, salvo que cada servidor puede tener varias activaciones del mismo grano y el grano no está registrado en el directorio de granos, ya que no es necesario.
Esta estrategia de colocación se configura agregando StatelessWorkerAttribute a un grano.
Colocación basada en roles de silo
Una estrategia de colocación determinista que coloca granos en silos con un rol específico. Esta estrategia de colocación se configura agregando SiloRoleBasedPlacementAttribute a un grano.
Colocación optimizada de recursos
La estrategia de selección de ubicación optimizada para recursos intenta optimizar los recursos del clúster al equilibrar las activaciones específicas entre silos en función de la memoria disponible y el uso de CPU. Asigna ponderaciones a las estadísticas en tiempo de ejecución para priorizar los distintos recursos y calcula una puntuación normalizada para cada silo. Se elige el silo con la puntuación más baja para colocar la próxima activación. La normalización garantiza que cada propiedad contribuye proporcionalmente a la puntuación general. Los pesos se pueden ajustar a través de las ResourceOptimizedPlacementOptions basadas en los requisitos y prioridades específicos del usuario para diferentes recursos.
Además, esta estrategia de selección de ubicación expone una opción para crear una preferencia más fuerte para el silo local (el que obtuvo la solicitud para realizar una nueva selección de ubicación) que se seleccionará como destino para la activación. Esto se controla a través de la propiedad LocalSiloPreferenceMargin
que forma parte de las opciones.
Además, un algoritmo adaptable en línea proporciona un efecto suavizador que evita caídas rápidas de señales mediante su transformación en un proceso de descomposición polinómica. Esto es especialmente importante para el uso de la CPU y, en general, contribuye a evitar la saturación de los recursos en los silos, especialmente en los recién integrados.
Este algoritmo se basa en: ubicación basada en recursos con el filtrado de Kalman en modo dual cooperativo
Esta estrategia de colocación se configura agregando ResourceOptimizedPlacementAttribute a un grano.
Elegir una estrategia de colocación
Elegir la estrategia de colocación de granos adecuada, más allá de los valores predeterminados que proporciona Orleans, requiere monitorización y evaluación por parte del desarrollador. La elección de la estrategia de selección de ubicación debe basarse en el tamaño y la complejidad de la aplicación, las características de carga de trabajo y el entorno de implementación.
La colocación aleatoria se basa en la ley de números grandes, por lo que suele ser un valor predeterminado bueno cuando hay una carga imprevisible distribuida en una gran cantidad de granos (más de 10 000).
La colocación basada en recuento de activación también tiene un elemento aleatorio, basándose en el principio Power of Two Choices, que es un algoritmo usado habitualmente para el equilibrio de carga distribuido y se usa en equilibradores de carga populares. Los silos publican con frecuencia estadísticas en tiempo de ejecución en otros silos del clúster, entre los que se incluyen los siguientes:
- Memoria disponible, memoria física total y uso de memoria.
- Uso de CPU.
- Recuento total de activación y recuento de activación activa reciente.
- Ventana deslizante de las activaciones que estaban activas en los últimos segundos, a veces denominada conjunto de trabajo de activación.
A partir de estas estadísticas, solo se usan actualmente los recuentos de activación para determinar la carga en un silo determinado.
En última instancia, debe experimentar con diferentes estrategias y supervisar las métricas de rendimiento para determinar la mejor opción. Al seleccionar la estrategia adecuada de colocación de granos, puede optimizar el rendimiento, la escalabilidad y la rentabilidad de las aplicaciones de Orleans.
Configurar la estrategia de ubicación predeterminada
Orleans usará la colocación aleatoria a menos que se invalide el valor predeterminado. La estrategia de selección de ubicación predeterminada se puede invalidar registrando una implementación de PlacementStrategy durante la configuración:
siloBuilder.ConfigureServices(services =>
services.AddSingleton<PlacementStrategy, MyPlacementStrategy>());
Configuración de la estrategia de colocación de un grano
La estrategia de selección de ubicación de un tipo de grano se configura agregando el atributo adecuado en la clase de grano. Los atributos pertinentes se especifican en las secciones de estrategias de ubicación .
Ejemplo de estrategia de colocación personalizada
En primer lugar, defina una clase que implemente IPlacementDirector interfaz, lo que requiere un único método. En este ejemplo, se supone que tiene una función GetSiloNumber
definida que devolverá un número de silo según el Guid del grano que se va a crear.
public class SamplePlacementStrategyFixedSiloDirector : IPlacementDirector
{
public Task<SiloAddress> OnAddActivation(
PlacementStrategy strategy,
PlacementTarget target,
IPlacementContext context)
{
var silos = context.GetCompatibleSilos(target).OrderBy(s => s).ToArray();
int silo = GetSiloNumber(target.GrainIdentity.PrimaryKey, silos.Length);
return Task.FromResult(silos[silo]);
}
}
A continuación, debe definir dos clases para permitir que las clases de grano se asignen a la estrategia:
[Serializable]
public sealed class SamplePlacementStrategy : PlacementStrategy
{
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class SamplePlacementStrategyAttribute : PlacementAttribute
{
public SamplePlacementStrategyAttribute() :
base(new SamplePlacementStrategy())
{
}
}
A continuación, simplemente etiquete las clases de grano que quiera usar esta estrategia con el atributo :
[SamplePlacementStrategy]
public class MyGrain : Grain, IMyGrain
{
// ...
}
Por último, registre la estrategia al construir el SiloHost:
private static async Task<ISiloHost> StartSilo()
{
var builder = new HostBuilder(c =>
{
// normal configuration methods omitted for brevity
c.ConfigureServices(ConfigureServices);
});
var host = builder.Build();
await host.StartAsync();
return host;
}
private static void ConfigureServices(IServiceCollection services)
{
services.AddPlacementDirector<SamplePlacementStrategy, SamplePlacementStrategyFixedSiloDirector>();
}
Para obtener un segundo ejemplo sencillo que muestra un uso adicional del contexto de selección de ubicación, consulte PreferLocalPlacementDirector
en Orleans el repositorio de origen.