Udostępnij za pośrednictwem


Koszt przenoszenia usług

Czynnikiem rozważanym przez menedżera zasobów klastra usługi Service Fabric podczas próby określenia, jakie zmiany należy wprowadzić w klastrze, jest koszt tych zmian. Pojęcie "kosztu" jest wymieniane z tym, ile można ulepszyć klastra. Koszt jest uwzględniany podczas przenoszenia usług na potrzeby równoważenia, defragmentacji i innych wymagań. Celem jest spełnienie wymagań w najmniej destrukcyjny lub kosztowny sposób.

Przenoszenie usług kosztuje co najmniej czas procesora CPU i przepustowość sieci. W przypadku usług stanowych wymaga skopiowania stanu tych usług, zużywania dodatkowej pamięci i dysku. Minimalizacja kosztów rozwiązań dostarczanych przez usługę Azure Service Fabric Cluster Resource Manager pomaga zagwarantować, że zasoby klastra nie są niepotrzebnie wydawane. Nie chcesz jednak ignorować rozwiązań, które znacząco poprawiłyby alokację zasobów w klastrze.

Menedżer zasobów klastra ma dwa sposoby obliczania kosztów i ogranicza je podczas próby zarządzania klastrem. Pierwszy mechanizm polega po prostu na liczeniu każdego ruchu, który by to zrobić. Jeśli dwa rozwiązania są generowane z około tego samego salda (wynik), menedżer zasobów klastra preferuje ten z najniższym kosztem (łączna liczba ruchów).

Ta strategia działa dobrze. Ale podobnie jak w przypadku obciążeń domyślnych lub statycznych, jest mało prawdopodobne w każdym złożonym systemie, że wszystkie ruchy są równe. Niektóre mogą być znacznie droższe.

Ustawianie kosztów przenoszenia

Domyślny koszt przeniesienia dla usługi można określić podczas jej tworzenia:

Program PowerShell:

New-ServiceFabricService -ApplicationName $applicationName -ServiceName $serviceName -ServiceTypeName $serviceTypeName –Stateful -MinReplicaSetSize 3 -TargetReplicaSetSize 3 -PartitionSchemeSingleton -DefaultMoveCost Medium

C#:

FabricClient fabricClient = new FabricClient();
StatefulServiceDescription serviceDescription = new StatefulServiceDescription();
//set up the rest of the ServiceDescription
serviceDescription.DefaultMoveCost = MoveCost.Medium;
await fabricClient.ServiceManager.CreateServiceAsync(serviceDescription);

Możesz również określić lub zaktualizować pozycję MoveCost dynamicznie dla usługi po utworzeniu usługi:

Program PowerShell:

Update-ServiceFabricService -Stateful -ServiceName "fabric:/AppName/ServiceName" -DefaultMoveCost High

C#:

StatefulServiceUpdateDescription updateDescription = new StatefulServiceUpdateDescription();
updateDescription.DefaultMoveCost = MoveCost.High;
await fabricClient.ServiceManager.UpdateServiceAsync(new Uri("fabric:/AppName/ServiceName"), updateDescription);

Dynamiczne określanie kosztów przenoszenia na podstawie repliki

Poprzednie fragmenty kodu służą do określania elementu MoveCost dla całej usługi jednocześnie spoza samej usługi. Jednak koszt przenoszenia jest najbardziej przydatny, gdy koszt przeniesienia określonego obiektu usługi zmienia się w ciągu jego cyklu życia. Ponieważ same usługi prawdopodobnie mają najlepszy pomysł na to, jak kosztowne są przenoszenie danego czasu, istnieje interfejs API dla usług, aby zgłosić własny koszt przenoszenia indywidualnego w czasie wykonywania.

C#:

this.Partition.ReportMoveCost(MoveCost.Medium);

Uwaga

Koszt przenoszenia replik pomocniczych można ustawić tylko za pomocą kodu.

Raportowanie kosztów przenoszenia dla partycji

W poprzedniej sekcji opisano sposób, w jaki repliki usługi lub wystąpienia zgłaszają same dane przenoszenia. Udostępniliśmy interfejs API usługi Service Fabric do raportowania wartości MoveCost w imieniu innych partycji. Czasami replika usługi lub wystąpienie nie może określić najlepszej wartości MoveCost samodzielnie i musi polegać na innych logiki usług. Raportowanie elementu MoveCost w imieniu innych partycji, wraz z raportowaniem obciążenia w imieniu innych partycji, umożliwia całkowite zarządzanie partycjami spoza. Te interfejsy API eliminują potrzeby wzorca przyczepki z perspektywy menedżera zasobów klastra.

Aktualizacje MoveCost można zgłosić dla innej partycji z tym samym wywołaniem interfejsu API. Należy określić obiekt PartitionMoveCostDescription dla każdej partycji, którą chcesz zaktualizować przy użyciu nowych wartości moveCost. Interfejs API umożliwia aktualizowanie elementu MoveCost na wiele sposobów:

  • Partycja usługi stanowej może zaktualizować replikę podstawową MoveCost.
  • Zarówno bezstanowe, jak i stanowe usługi mogą aktualizować wartość MoveCost wszystkich jej replik pomocniczych lub wystąpień.
  • Zarówno usługi bezstanowe, jak i stanowe mogą aktualizować pozycję MoveCost określonej repliki lub wystąpienia w węźle.

Każda aktualizacja MoveCost dla partycji powinna zawierać co najmniej jedną prawidłową wartość, która zostanie zmieniona. Na przykład można pominąć aktualizację repliki podstawowej z przypisaniem wartości null do wpisu repliki podstawowej, inne wpisy będą używane podczas aktualizacji MoveCost i pominiemy aktualizację MoveCost dla repliki podstawowej. Ponieważ aktualizacja elementu MoveCost dla wielu partycji przy użyciu pojedynczego wywołania interfejsu API jest możliwa, interfejs API udostępnia listę kodów zwracanych dla odpowiedniej partycji. Jeśli pomyślnie zaakceptujemy i przetworzymy żądanie aktualizacji MoveCost, zwracany kod będzie powodzeniem. W przeciwnym razie interfejs API udostępnia kod błędu:

  • PartitionNotFound — określony identyfikator partycji nie istnieje.
  • ReconfigurationPending — partycja jest obecnie ponownie konfigurowana.
  • InvalidForStatelessServices — podjęto próbę zmiany elementu MoveCost repliki podstawowej dla partycji należącej do usługi bezstanowej.
  • ReplicaDoesNotExist — replika pomocnicza lub wystąpienie nie istnieje w określonym węźle.
  • InvalidOperation — aktualizowanie elementu MoveCost dla partycji należącej do aplikacji systemowej.

C#:

Guid partitionId = Guid.Parse("53df3d7f-5471-403b-b736-bde6ad584f42");
string nodeName0 = "NodeName0";

OperationResult<UpdatePartitionMoveCostResultList> updatePartitionMoveCostResults =
    await this.FabricClient.UpdatePartitionMoveCostAsync(
        new UpdatePartitionMoveCostQueryDescription
        {
            new List<PartitionMoveCostDescription>()
            {
                new PartitionMoveCostDescription(
                    partitionId,
                    MoveCost.VeryHigh,
                    MoveCost.Zero,
                    new List<ReplicaMoveCostDescription>()
                    {
                        new ReplicaMoveCostDescription(nodeName0, MoveCost.Medium)
                    })
            }
        },
        this.Timeout,
        cancellationToken);

W tym przykładzie wykonasz aktualizację ostatniego zgłoszonego kosztu przeniesienia dla partycji 53df3d7f-5471-403b-b736-bde6ad584f42. Koszt przenoszenia repliki podstawowej będzie bardzo szybki. Koszt przenoszenia wszystkich replik pomocniczych będzie równy zero, z wyjątkiem kosztów przenoszenia dla określonej repliki pomocniczej znajdującej się w węźle NodeName0. Koszt przenoszenia dla określonej repliki będzie średni. Jeśli chcesz pominąć aktualizowanie kosztów przenoszenia dla repliki podstawowej lub wszystkich replik pomocniczych, możesz pozostawić odpowiedni wpis jako null.

Wpływ kosztów przenoszenia

MoveCost ma pięć poziomów: Zero, Low, Medium, High i VeryHigh. Obowiązują następujące zasady:

  • MoveCosts są względem siebie nawzajem, z wyjątkiem Zero i VeryHigh.
  • Zerowy koszt przenoszenia oznacza, że ruch jest wolny i nie powinien być liczone względem wyniku rozwiązania.
  • Ustawienie kosztu przeniesienia na wartość High lub VeryHigh nie zapewnia gwarancji, że replika nigdy nie zostanie przeniesiona.
  • Repliki z kosztem przenoszenia VeryHigh zostaną przeniesione tylko w przypadku naruszenia ograniczeń w klastrze, którego nie można naprawić w żaden inny sposób (nawet jeśli wymaga przeniesienia wielu innych replik w celu naprawienia naruszenia)

Przenoszenie kosztów jako czynnika podczas wybierania replik do przenoszenia

MoveCost pomaga znaleźć rozwiązania, które powodują najmniejsze zakłócenia ogólne i są najłatwiejsze do osiągnięcia, mimo że nadal docierają do równoważnej równowagi. Pojęcie kosztów usługi może być związane z wieloma elementami. Najczęstsze czynniki obliczania kosztów przenoszenia to:

  • Ilość stanu lub danych, które usługa musi przenieść.
  • Koszt rozłączenia klientów. Przenoszenie repliki podstawowej jest zwykle bardziej kosztowne niż koszt przenoszenia repliki pomocniczej.
  • Koszt przerwania operacji w locie. Niektóre operacje na poziomie magazynu danych lub operacje wykonywane w odpowiedzi na wywołanie klienta są kosztowne. Po pewnym momencie nie chcesz ich zatrzymywać, jeśli nie musisz. W związku z tym podczas wykonywania operacji zwiększasz koszt przenoszenia tego obiektu usługi, aby zmniejszyć prawdopodobieństwo przeniesienia. Po zakończeniu operacji należy ustawić koszt z powrotem na normalny.

Ważne

Użycie kosztu przenoszenia VeryHigh należy dokładnie rozważyć, ponieważ znacznie ogranicza możliwość menedżera zasobów klastra w celu znalezienia rozwiązania do globalnego optymalnego umieszczania w klastrze. Repliki z kosztem przenoszenia VeryHigh zostaną przeniesione tylko w przypadku naruszenia ograniczeń w klastrze, którego nie można naprawić w żaden inny sposób (nawet jeśli wymaga przeniesienia wielu innych replik w celu naprawienia naruszenia)

Włączanie kosztów przenoszenia w klastrze

Aby uwzględnić bardziej szczegółowe elementy MoveCosts, w klastrze należy włączyć pozycję MoveCost. Bez tego ustawienia domyślny tryb liczenia ruchów jest używany do obliczania elementu MoveCost, a raporty MoveCost są ignorowane.

ClusterManifest.xml:

        <Section Name="PlacementAndLoadBalancing">
            <Parameter Name="UseMoveCostReports" Value="true" />
        </Section>

za pośrednictwem ClusterConfig.json dla wdrożeń autonomicznych lub Template.json dla klastrów hostowanych na platformie Azure:

"fabricSettings": [
  {
    "name": "PlacementAndLoadBalancing",
    "parameters": [
      {
          "name": "UseMoveCostReports",
          "value": "true"
      }
    ]
  }
]

Następne kroki