Freigeben über


Kornplatzierung

Orleans stellt sicher, dass beim Ausführen eines Grain-Aufrufs eine Instanz dieses Grains im Arbeitsspeicher auf einem Server im Cluster zur Verarbeitung der Anforderung verfügbar ist. Wenn das Getreide derzeit nicht im Cluster aktiv ist, wählt Orleans einen der Server aus, um das Korn zu aktivieren. Dies wird als Grainplatzierungbezeichnet. Die Platzierung ist auch eine Möglichkeit, die Last auszugleichen: Die gleichmäßige Platzierung von ausgelasteten Grains trägt dazu bei, die Workload im gesamten Cluster auszugleichen.

Der Platzierungsprozess in Orleans ist vollständig konfigurierbar: Entwickler können aus einer Reihe von vorgefertigten Richtlinien für die Platzierung auswählen, z. B. „random“ (zufällig), „prefer-local“ (lokal bevorzugen) und „load-based“ (lastbasiert), oder eine benutzerdefinierte Logik festlegen. Dies ermöglicht volle Flexibilität bei der Entscheidung, wo Getreide entsteht. So können z. B. Getreide auf einem Server in der Nähe der Ressourcen platziert werden, an denen sie arbeiten müssen, oder in der Nähe anderer Getreide, mit denen sie kommunizieren. Standardmäßig wählt Orleans einen zufällig kompatiblen Server aus.

Die Platzierungsstrategie, die Orleans verwendet, kann global oder pro Kornklasse konfiguriert werden.

Zufällige Platzierung

Ein Server wird zufällig von den kompatiblen Servern im Cluster ausgewählt. Diese Platzierungsstrategie wird durch Hinzufügen der RandomPlacementAttribute-Instanz zu einem Grain konfiguriert.

Lokale Platzierung

Wenn der lokale Server kompatibel ist, wählen Sie den lokalen Server aus, andernfalls einen zufälligen Server. Diese Platzierungsstrategie wird durch Hinzufügen der PreferLocalPlacementAttribute-Instanz zu einem Grain konfiguriert.

Hashbasierte Platzierung

Hashen Sie die Korn-ID auf eine nicht negative ganze Zahl, und modulieren Sie sie mit der Anzahl der kompatiblen Server. Wählen Sie den entsprechenden Server aus der Liste der kompatiblen Server aus, die nach Serveradresse sortiert sind. Beachten Sie, dass dies nicht garantiert bleibt, da sich die Clustermitgliedschaft ändert. Insbesondere kann das Hinzufügen, Entfernen oder Neustarten von Servern den für eine bestimmte Grain-ID ausgewählten Server ändern. Da Grains, die diese Strategie verwenden, im Grain-Verzeichnis registriert sind, hat diese Änderung der Platzierungsentscheidung, wenn sich die Mitgliedschaft ändert, in der Regel keinen spürbaren Effekt.

Diese Platzierungsstrategie wird durch Hinzufügen der HashBasedPlacementAttribute-Instanz zu einem Grain konfiguriert.

Platzierung auf Basis der Aktivierungsanzahl

Diese Platzierungsstrategie beabsichtigt, neue Getreideaktivierungen auf dem am wenigsten stark geladenen Server basierend auf der Anzahl der zuletzt ausgelasteten Getreide zu platzieren. Es enthält einen Mechanismus, in dem alle Server regelmäßig ihre Gesamtaktivierungsanzahl auf allen anderen Servern veröffentlichen. Der Platzierungsdirektor wählt dann einen Server aus, von dem vorhergesagt wird, dass er die wenigsten Aktivierungen haben wird. Dies geschieht, indem er die zuletzt gemeldete Aktivierungsanzahl überprüft und die aktuelle Aktivierungsanzahl basierend auf der kürzlich getätigten Aktivierungsanzahl auf dem aktuellen Server prognostiziert. Der Director wählt bei dieser Vorhersage mehrere Server zufällig aus, um zu vermeiden, dass mehrere separate Server denselben Server überladen. Standardmäßig werden zwei Server zufällig ausgewählt, aber dieser Wert kann über ActivationCountBasedPlacementOptionskonfiguriert werden.

Dieser Algorithmus basiert auf der These The Power of Two Choices in Randomized Load Balancing von Michael David Mitzenmacherund wird auch in Nginx für den verteilten Lastenausgleich verwendet, wie im Artikel NGINX und der "Power of Two Choices" Load-Balancing Algorithmusbeschrieben.

Diese Platzierungsstrategie wird durch Hinzufügen der ActivationCountBasedPlacementAttribute-Instanz zu einem Grain konfiguriert.

Zustandslose Workerplatzierung

Zustandslose Workerplatzierung ist eine spezielle Platzierungsstrategie, die von zustandslosen Workern Grainsverwendet wird. Diese Platzierung funktioniert fast identisch mit PreferLocalPlacement, außer dass jeder Server mehrere Aktivierungen desselben Getreides haben kann und das Getreide nicht im Getreideverzeichnis registriert ist, da es keine Notwendigkeit gibt.

Diese Platzierungsstrategie wird durch Hinzufügen der StatelessWorkerAttribute-Instanz zu einem Grain konfiguriert.

Platzierung auf Basis der Silorolle

Eine deterministische Platzierungsstrategie, die Getreide auf Silos mit einer bestimmten Rolle platziert. Diese Platzierungsstrategie wird durch Hinzufügen der SiloRoleBasedPlacementAttribute-Instanz zu einem Grain konfiguriert.

Ressourcenoptimierte Platzierung

Die ressourcenoptimierte Platzierungsstrategie versucht, Clusterressourcen zu optimieren, indem die Kornaktivierungen auf Basis des verfügbaren Arbeitsspeichers und der CPU-Auslastung über Silos hinweg ausgeglichen werden. Sie weist Laufzeitstatistiken Gewichtungen zu, um unterschiedliche Ressourcen zu priorisieren und eine normalisierte Bewertung für jeden Silo zu berechnen. Das Silo mit der niedrigsten Bewertung wird für die Platzierung der bevorstehenden Aktivierung ausgewählt. Normalisierung stellt sicher, dass jede Eigenschaft proportional zur Gesamtbewertung beiträgt. Gewichtungen können über die ResourceOptimizedPlacementOptions basierend auf benutzerspezifischen Anforderungen und Prioritäten für unterschiedliche Ressourcen angepasst werden.

Darüber hinaus stellt diese Platzierungsstrategie eine Option zur Verfügung, um eine stärkere Präferenz für das lokale Silo zu erstellen (das, das die Anforderung erhalten hat, eine neue Platzierung zu erstellen), das als Ziel für die Aktivierung ausgewählt wird. Dies wird über die LocalSiloPreferenceMargin Eigenschaft gesteuert, die Teil der Optionen ist.

Außerdem bietet ein adaptiver Online-Algorithmus einen Glättungseffekt, der schnelle Signalabbrüche verhindert, indem er in einen polynomähnlichen Verfallsprozess umgewandelt wird. Dies ist besonders wichtig für die CPU-Auslastung und trägt insgesamt dazu bei, die Ressourcensättigung auf den Silos zu vermeiden, insbesondere bei neu hinzugekommenen.

Dieser Algorithmus basiert auf: Ressourcenbasierte Platzierung mit kooperativem Kalman-Filter

Diese Platzierungsstrategie wird durch Hinzufügen der ResourceOptimizedPlacementAttribute-Instanz zu einem Grain konfiguriert.

Auswählen einer Platzierungsstrategie

Die Auswahl der geeigneten Getreideplatzierungsstrategie, die über die von Orleans bereitgestellten Standardwerte hinausgeht, erfordert Überwachung und Entwicklerbewertung. Die Wahl der Platzierungsstrategie sollte auf der Größe und Komplexität der App, der Workloadmerkmale und der Bereitstellungsumgebung basieren.

Die zufällige Platzierung beruht auf dem Gesetz der großen Zahlen, sodass sie in der Regel ein geeigneter Standard ist, wenn eine unvorhersehbare Last auf eine große Anzahl von Grains (10.000 und mehr) verteilt ist.

Die auf der Aktivierungsanzahl basierende Platzierung enthält auch ein zufälliges Element, das auf dem „Power of Two Choices“-Prinzip basiert, einem häufig verwendeten Algorithmus für den verteilten Lastenausgleich, der in beliebten Load Balancern eingesetzt wird. Silos veröffentlichen häufig Laufzeitstatistiken für andere Silos im Cluster, darunter:

  • Verfügbarer Arbeitsspeicher, gesamter physischer Speicher und Speicherauslastung.
  • CPU-Auslastung.
  • Die Gesamtzahl der Aktivierungen und die Anzahl der kürzlich aktiven Aktivierungen.
    • Ein gleitendes Fenster von Aktivierungen, die in den letzten Sekunden aktiv waren, manchmal auch als Aktivierungsarbeitssatz bezeichnet.

Aus diesen Statistiken werden derzeit nur die Aktivierungsanzahlen verwendet, um die Last eines bestimmten Silos zu ermitteln.

Letztendlich sollten Sie mit verschiedenen Strategien experimentieren und Leistungsmetriken überwachen, um die optimale Anpassung zu ermitteln. Indem Sie die richtige Strategie für die Kornplatzierung auswählen, können Sie die Leistung, Skalierbarkeit und Kosteneffizienz Ihrer Orleans-Apps optimieren.

Konfigurieren der Standardplatzierungsstrategie

Orleans verwendet eine zufällige Platzierung, es sei denn, die Standardeinstellung wird überschrieben. Die Standardplatzierungsstrategie kann überschrieben werden, indem eine Implementierung von PlacementStrategy während der Konfiguration registriert wird:

siloBuilder.ConfigureServices(services =>
    services.AddSingleton<PlacementStrategy, MyPlacementStrategy>());

Konfigurieren der Platzierungsstrategie für ein Korn

Die Platzierungsstrategie für einen Korntyp wird durch Hinzufügen des entsprechenden Attributs zur Kornklasse konfiguriert. Die relevanten Attribute werden in den Platzierungsstrategien Abschnitten angegeben.

Beispiel für eine benutzerdefinierte Platzierungsstrategie

Definieren Sie zunächst eine Klasse, die IPlacementDirector Schnittstelle implementiert, die eine einzelne Methode erfordert. In diesem Beispiel gehen wir davon aus, dass Sie die Funktion GetSiloNumber definiert haben, die eine Silonummer mit der Guid des zu erstellenden Grains zurückgibt.

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]);
    }
}

Anschließend müssen Sie zwei Klassen definieren, damit der Strategie Getreideklassen zugewiesen werden können:

[Serializable]
public sealed class SamplePlacementStrategy : PlacementStrategy
{
}

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public sealed class SamplePlacementStrategyAttribute : PlacementAttribute
{
    public SamplePlacementStrategyAttribute() :
        base(new SamplePlacementStrategy())
    {
    }
}

Markieren Sie dann einfach alle Kornklassen, die Sie mit dieser Strategie und dem Attribut verwenden möchten:

[SamplePlacementStrategy]
public class MyGrain : Grain, IMyGrain
{
    // ...
}

Registrieren Sie abschließend die Strategie, wenn Sie den SiloHost erstellen:

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>();
}

Ein zweites einfaches Beispiel, das die weitere Verwendung des Platzierungskontexts zeigt, finden Sie unter PreferLocalPlacementDirector im Orleans-Quellrepository.