Hallo!
Ich habe folgendes Problem:
Ich habe einen WebService, welcher Anfragen an ein Programm (welches auch auf einem anderen Rechner laufen kann) weiterleitet. Nun soll der WebService diese Anfragen zur Lastverteilung auf mehrere Programme (und somit evtl. mehrere Rechner) verteilen können.
Da bei jeder Anfrage an den WebService einen neue Instanz von diesem im WebServer erstellt wird, und auch die Möglichkeit besteht, dass mehrere Instanzen aufgrund der Anfragen nahezu zeitgleich erzeugt werden, bräuchte ich eine Komponente, auf welche alle Instanzen gleichermassen Zugriff haben und die gleichzeitig auch threadsicher ist.
Dann könnte in dieser Komponente im einfachsten Fall ein Zähler laufen, wobei nur getestet wird, ob die aktuelle Anfrage bei einem graden oder ungraden Zählerstand erfolgt.
Eine Möglichkeit wäre natürlich eine Datei zu erstellen, aber dies erscheint mir zu ressourcenhungrig.
Weiss jemand eine Lösung, bzw. hab' ich mich überhaupt verständlich genug ausgedrückt ...?
Nobody is perfect. I'm sad, i'm not nobody 🙁
Also wenn es auf mehreren Rechner laufen soll, dann nimmst am besten eine DB wo jeder Recher zugriff hat.
Ansonsten eine Service, dass allen Rechner zugriff gibt.
@Ifoko:
Db ist sogar 'ne interessante idee, werd' ich mal als alternative behalten.
Das einzige, was mich dabei ein wenig stört, ist die Tatsache, dafür eine DB aufzubauen (ok, geht mit mysql super schnell).
Mein Wunsch läge eigentlich in einer dll oder einem dienst, welche(r) einmal im speicher vorliegt, und von allen WebService-Instanzen gleichermassen aufgerufen werden könnte. vorteil wäre, dass weder ein zugriff der komponenten auf das dateisystem oder ein db-system erfolgen muss. es wird einfach ein zähler erhöht und zurückgegeben.
kann man da evtl. was über die Windows-Mitteilungen machen, und wenn, wie erhält der webservice die antwort???
eine andere möglichkeit, die mir grade noch einfällt, wäre die möglichkeit über tcp-verbindungen: auf demselben rechner, auf dem auch der webserver läuft, läuft ein dienst im hintergrund, welcher auf einem port auf anfragen wartet (da lokal, kann ja sogar die firewall unberührt bleiben).
ist aber auch schon ein wenig so wie mit kanonen auf spatzen zu schiessen gg. aber ist noch 'ne alternative.
hoffentlich hat hier noch jemand eine bessere lösung ....
Nobody is perfect. I'm sad, i'm not nobody 🙁
Original von tom-essen
Da bei jeder Anfrage an den WebService einen neue Instanz von diesem im WebServer erstellt wird, und auch die Möglichkeit besteht, dass mehrere Instanzen aufgrund der Anfragen nahezu zeitgleich erzeugt werden, bräuchte ich eine Komponente, auf welche alle Instanzen gleichermassen Zugriff haben und die gleichzeitig auch threadsicher ist.
Das schreit nach Sessions. Damit kannst du sorgen, dass mehrere Aufrufe ein und die gleiche Service-Instanz nutzen. Für Threadsicherheit musst du selbst sorgen. Damit kannst du auch leicht zustandsbehaftete WS basteln.
Load Balacing würde aber die Last auf verschiedene Rechner verteilen. So kannst du natürlich klassisches HTTP-Load Balancing machen (verschiedenen URLs werden zu verschiedenen Rechnern geroutet). Dort hängt dann jeweils ein WCF-Server.
So richtig automatisch geht da aber noch nix. Ich würde erwarten dass da was mit Vista-Server kommt. Applikationsseitiges Load Balancing ist zwar leistungsfähig, aber auch kompliziert. Eigentlich will man ja nur einen LoadBalancer konfigurieren, der dann die Services automatisch verteilen und zugleich die Hosts instanziiert, ohne dass man dafür was tun muss (außer konfigurieren).
Sessions und Load Balancing sind natürlich in Kombination nicht möglich oder sinnvoll, da eine Session performant zur einem Server zugeordnet werden kann. Load Balacing ist also zustandslosen Diensten vorbehalten.
Wie meinst Du das mit der neuen Instanz?
Wenn es sich um einen ASP.NET Webservice handelt, laufen die alle unter dem aspnet-workerprozess, und der wird nicht beendet. Dann reicht dir ein statischer Member in deiner Webservice-Klasse oder ein Eintrag in der Application[]-Collection. Im Konstruktor kannst Du dann diesen dann durch lock() threadsafe für weitere Auswertungen puffern.
class MyWebService: System.Web.Services.WebService
{
int selector = 0;
MyWebService()
{
if(Application["Selector"]==null)
{
Application["Selector"] = selector;
}
else
{
lock(Application["Selector"])
{
selector = (int)Application["Selector"];
selector ++;
Application["Selector"] = selector;
}
}
}
/*
WebMethods
*/
}
Oder hab ich Dich jetzt völlig falsch verstanden?
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
Die Frage ist:
Gibts 1 Server oder mehrere Server wo die Services laufen.
1 Server dann alles kp
meherer Server dann brauchst 1 zentrale DB oder Ähnliches.
lg
Wenns mehrere Server gibt, kann man einen zentralen Webservice zur Verfügung stellen, der nichts anderes als mein Beispiel von oben tut und dann "selector" per WebMethod zurückgibt. An den können sich dann die verteilten Server wenden 🙂
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
Also:
Es gibt einen Rechner, auf dem der IIS läuft.
Dort ist ein WebService hinterlegt.
Wenn nun z.B. zwei externe Rechner zur gleichen Zeit Anfragen an diesen WebService richten, werden doch auch zwei Instanzen des WebService erstellt, oder?
Funktioniert das dann trotzdem mit der statischen Instanz. Es ist doch eher so, als wenn ich zweimal dasselbe Programm starte, oder?
Nobody is perfect. I'm sad, i'm not nobody 🙁
Wenn das alles auf einem IIS läuft, kannst du so vorgehen, wie ich oben gepostet habe. Der asp.net-Prozess stellt dem Webservice die Appliation-Collection zur Verfügung. So eine Collection gibts einmal für jeden Webservice im IIS. Da der asp-Prozess weiterlebt und nicht beendet wird ausser wenn Du den IIS beendest, ist diese Collection dann quasi für alle Threads statisch.
Andersrum gesagt: Es werden zwar 2 Instanzen des Webservice erdtellt, diese laufen aber im selben Prozesss. Dies ist der ASP-Prozess (aspwp.exe), der weiterlebt un damit Applikationsdaten für den gesamten Webservice halten kann.
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca
@All:
Erstmal ein grosses Dankeschön für die vielen Tipps und Anregungen.
Ich werd's aber heute nicht mehr ausprobieren, bin irgendwie total fertig.
@MarsStein:
Wenn das hinhaut, ist's genau das, was ich gesucht habe.
Ich melde mich, sobald ich getestet habe 🙂
Nobody is perfect. I'm sad, i'm not nobody 🙁
Der IIS unterstützt Clustering ab Version 6, out-of-the-box. Dafür werden Anfragen auf verschiedenen Threads ausgelagert, d.h. mehrere Workerprozesse. Man muss halt nur mit dem Sassions aufpassen.
"Das Problem kennen ist wichtiger, als die Lösung zu finden, denn die genaue Darstellung des Problems führt automatisch zur richtigen Lösung." Albert Einstein
1 Server -> wie MarcStein oder so Ähnlich (unlock nicht vergessen)
lock(var){...} ist eine Blockanweisung, wenn die geschweifte Klammer geschlossen wird, ist die Variable wieder frei. Ein "unlock" gibts meines Wissens nicht.
Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca