Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In Lernprogramm II haben wir uns mit einem zeitaufwändigen Dienst beschäftigt, indem wir eine dauerhafte Sitzung verwenden. Der Batchmodus ist jedoch nicht der einzige Berechnungsmodus in der HPC-Welt. Einige Berechnungen können innerhalb weniger Sekunden bis zu einigen Minuten abgeschlossen werden. Der Endbenutzer erwartet möglicherweise fast echtzeitbasierte Antwort.
Dieser Modus bringt unterschiedliche Herausforderungen im Vergleich zum Batchmodus. Die Reaktionszeit ist wichtiger. Daher kann der Sitzungsstartaufwand nicht ignoriert werden. In einem typischen HPC-Cluster dauert es ein paar Sekunden, eine neue Sitzung zu starten. Wenn im Cluster andere Aufträge ausgeführt werden, muss die neu erstellte Sitzung warten, bis die Ressourcen verfügbar sind, wodurch die Startzeit viel länger ist. Glücklicherweise bietet HPC Pack eine Möglichkeit, mit dieser Situation umzugehen und die unnötigen Kosten zu senken.
Lesen Sie die zugehörigen Codebeispiels, um die Schritte in diesem Artikel auszuführen.
Implementieren des Diensts
Wir verwenden den gleichen Dienst wie in Lernprogramm II – dem Prime Factorization Service. Um die Anforderungen in Echtzeit zu erfüllen, übergeben wir nur kleine Zahlen an den Dienst.
Hier ist der Servicevertrag:
[ServiceContract]
public interface IPrimeFactorization
{
[OperationContract]
List<int> Factorize(int n);
}
Und hier ist die Dienstimplementierung:
public List<int> Factorize(int n)
{
List<int> factors = new List<int>();
for (int i = 2; n > 1;)
{
if (n % i == 0)
{
factors.Add(i);
n /= i;
}
else
{
i++;
}
}
return factors;
}
Implementieren des Clients
Um die Zeit beim Starten eines neuen Auftrags zu sparen, muss der Client die vorhandene Sitzung wiederverwenden, anstatt eine neue Sitzung zu erstellen, da das Erstellen einer neuen Sitzung bedeutet, einen neuen Auftrag zu starten. Um die vorhandene Sitzung wiederzuverwenden, müssen wir die Sitzung wie folgt erstellen:
const string headnode = "head.contoso.com";
const string serviceName = "PrimeFactorizationService";
SessionStartInfo info = new SessionStartInfo(headnode, serviceName);
//Enable session pool
info.ShareSession = true;
info.UseSessionPool = true;
Möglicherweise stellen Sie fest, dass hier zwei neue Eigenschaften von SessionStartInfo zugewiesen werden.
Das Festlegen von ShareSession auf "true" bedeutet, dass jeder Benutzer Anforderungen an den Broker senden kann, nicht nur die, die die Sitzung erstellt.
Durch Festlegen von UseSessionPool auf "true" wird sichergestellt, dass jeder neue Client die vorhandene Sitzung verwendet, anstatt eine andere zu erstellen. Der Sitzungspool wird auf serverseitiger Seite verwaltet . Es garantiert, dass ein Client, wenn ein Client eine Verbindung mit demselben Dienst herstellt, der auf "true" festgelegt ist, immer dieselbe Sitzung zurückgibt, solange er noch aktiv ist.
Jetzt können wir die Sitzung erstellen. Wir möchten keine dauerhafte Sitzung verwenden, da sie sich auf die Leistung auswirken kann.
//create an interactive session
using (Session session = Session.CreateSession(info))
{
Console.WriteLine("Session {0} has been created", session.Id);
…
}
Erstellen Sie einen Brokerclient, um Anforderungen zu senden und Antworten zu erhalten.
Im Falle des vorherigen Codes haben wir nun eine Situation, in der viele Brokerclients in einer einzigen Sitzung vorhanden sein können. In diesem Fall sollten wir dem Client eine eindeutige ID zuweisen.
//in one session, each broker client should have a unique id
string ClientId = Guid.NewGuid().ToString();
using (BrokerClient<IPrimeFactorization> client = new BrokerClient<IPrimeFactorization>(ClientId, session))
{
Console.WriteLine("BrokerClient {0} has been created", ClientId);
Random random = new Random();
int num = random.Next(1, Int32.MaxValue);
//Send request
FactorizeRequest request = new FactorizeRequest(num);
client.SendRequest<FactorizeRequest>(request, num);
client.EndRequests();
//Get response
foreach (BrokerResponse<FactorizeResponse> response in client.GetResponses<FactorizeResponse>())
{
int number = response.GetUserData<int>();
int[] factors = response.Result.FactorizeResult;
Console.WriteLine("{0} = {1}", number, string.Join<int>(" * ", factors));
}
}
Führen Sie nun den Client zweimal aus. Sie werden sehen, dass die Clients dieselbe Sitzungs-ID gemeinsam nutzen, als Ergebnis des aktivierten Sitzungspools. Außerdem wird der erste Client viel länger als die zweite ausgeführt, was angibt, dass der neue Client die erstellte Sitzung wiederverwendet.
Da GetResponses eine synchrone Funktion ist, wird der Client blockiert und wartet auf die Ergebnisse. Dies ist keine willkommene Situation in einem Echtzeitsystem, also versuchen wir es mit einer anderen Möglichkeit, Antworten zu erhalten.
Wir können einen asynchronen Rückruf für den Client mithilfe von SetResponseHandler wie folgt festlegen:
//use this event sync main thread and callback
AutoResetEvent done = newAutoResetEvent(false);
//set callback function. this handler will be invoke before service replies.
client.SetResponseHandler<FactorizeResponse>((response) =>
{
int number = response.GetUserData<int>();
int[] factors = response.Result.FactorizeResult;
Console.WriteLine("{0} = {1}", number, string.Join<int>(" * ", factors));
//release the lock
done.Set();
});
Daher kann der Client nach dem normalen Senden von Anforderungen mit anderen Arbeiten fortfahren. Wenn die Antworten bereit sind, wird der Antworthandler aufgerufen, um die Ergebnisse anzuzeigen.
Bereitstellen und Testen des Diensts
Sie können diesem Lernprogramm folgen, um den Fall schrittweise bereitzustellen und zu testen.
Sie können mehrere Clients ausführen. Die Ausgabe sieht wie folgt aus:
Beachten Sie, dass alle Clients dieselbe Sitzungs-ID verwenden.
Cluster automatisch vergrößern und automatisch verkleinern
Eine häufige Situation des interaktiven Modus besteht darin, einen lang andauernden Dienst auszuführen, der mehrere Clients bedient. Um so schnell wie möglich auf jede Anfrage zu reagieren, sollten wir die Sitzung lebendig halten. Andererseits ist es verschwenderisch, wenn ein SOA-Auftrag eine große Anzahl von Ressourcen in Zeiten außerhalb der Spitzenzeiten belegt.
HPC Pack verfügt über ein Feature zum Vergrößern und Verkleinern von Ressourcen basierend auf der Anzahl der Anforderungen. Wenn keine Anforderungen vorhanden sind, wird die Anzahl der Ressourcen auf die durch den Auftrag angegebene Mindestzahl verkleinert. Beim Empfangen von Anforderungen werden die Ressourcen automatisch vergrößert, um sie zu verarbeiten.
Hinweis: Eine Sitzung ist ein Timeout, wenn kein Client für einen bestimmten Zeitraum mit ihr verbunden ist. Um eine Sitzung zu einem Dienst mit langer Ausführung zu machen, können Sie die SessionIdleTimeout- beim Starten der Sitzung ändern.