Spring und RPC: Gleichzeitiger Zugriff von Clients auf Server-Methoden, was passiert

DarthShader

Erfahrenes Mitglied
Hallo zusammen,

ich habe eine Frage bezüglich Spring und dem veröffentlichen von Services via Spring-RPC. Wohlmöglich ist dies eine ziemliche Anfängerfrage, aber ich konnte darüber keine Informationen finden.

Nehmen wir an, ich möchte einen kleinen Server schreiben, der Spring verwendet. Über den Spring Context lege ich fest, dass es einen WriteHello - Service gibt, mit der Methode "WriteHello.write()". Clients können dann über RPC die "write()" MEthode des Servers aufrufen. Das funktioniert auch soweit, also kein großes Problem.

Meine Verständnisfrage geht dahin, dass ich nicht weiß, was passiert, wenn mehrere bzw. ganz viele Clients nun auf diese Methode zugreifen.

1. Der Port des RPC Aufrufs bzw. der Port auf dem der WriteHello-Service läuft, ist ja belegt. Beut ein Client nun eine Verbindung auf, so wird für die weitere Kommunikation zwischen Server und Client ja ein anderer Port genutzt, sodass der Listener-Port des Servers wieder frei wird, um weitere Verbindungen aufzunehmen, ist das so korrekt?

2. Abgesehen von den Ports, was passiert, wenn 2 Clients nun "WriteHello.write()" quasi "gleichzeitig" aufrufen wollen (was ja sicher passieren kann, wenn sehr viele Clients Verbindung aufnehmen). Erstellt Spring dann eine 2. Instanz der Implementierung von "WriteHello", oder werden alle Aufrufe auf ein und derselben Bean (also immer nur eine Instanz von WriteHello) geleitet? Falls letzteres der Fall ist, werden die Anfragen der Clients an den Server dann sequenziell auf dem Server abgearbeitet, es entstehen "von alleine" also keine Threads?


Über eine Antwort würde ich mich sehr freuen


Vielen Dank!


Ben
 
1. Der Port des RPC Aufrufs bzw. der Port auf dem der WriteHello-Service läuft, ist ja belegt. Beut ein Client nun eine Verbindung auf, so wird für die weitere Kommunikation zwischen Server und Client ja ein anderer Port genutzt, sodass der Listener-Port des Servers wieder frei wird, um weitere Verbindungen aufzunehmen, ist das so korrekt?

Das kann man so pauschal nicht sagen. Entscheidend ist, wie der Server die eingehende Anfrage abarbeitet. Verteilt er sie auf Threads, ist der Port nicht blockiert. Wird die Anfrage Synchron abgearbeitet ist der Port zu, solang der Server arbeitet.

2. Abgesehen von den Ports, was passiert, wenn 2 Clients nun "WriteHello.write()" quasi "gleichzeitig" aufrufen wollen (was ja sicher passieren kann, wenn sehr viele Clients Verbindung aufnehmen). Erstellt Spring dann eine 2. Instanz der Implementierung von "WriteHello", oder werden alle Aufrufe auf ein und derselben Bean (also immer nur eine Instanz von WriteHello) geleitet? Falls letzteres der Fall ist, werden die Anfragen der Clients an den Server dann sequenziell auf dem Server abgearbeitet, es entstehen "von alleine" also keine Threads?
Das kommt auf den Scope der Bean an. Per default sind die Singleton, d.h. alle Threads sehen die gleiche Instanz. Das ist der Grund warum die Beans halt Zustandslos sein sollen. Du kannst dir allerdings mit Spring problemlos einen ThreadScope basteln, der einzelne Instanzen an einen Thread bindet. Kritische Resourcen in einem ThreadLocal zu halten ist eine andere Möglichkeit, wenn auch weniger hübsch. Sequentiell werden calls nur, wenn du sie synchronized machst, was aber im Allgemeinen (ohne triftigen anderen Grund) keine gute Idee ist, da sowas halt dann schlecht skaliert.

Gruß
Ollie
 
Vielen Dank für Deine Antwort,

prinzipiell will ich ja nichts "exotisches". Ich möchte nur einen Server bauen, den man via RPC ansprechen kann, wobei ich dafür eben Spring nutzen möchte (ich bin begeistert davon, wie leicht es mit Spring ist, solche Service-Methoden zu "veröffentlichen"). Wenn man recht drüber nachdenkt, will ja ja das, was z.B. ein JBoss mit seinen Beans auch macht - der instanziiert diese ja bzw. holt sie bei einer Anfrage aus einem Pool.

Mein System muss auch keine große Last bewältigen, ich spreche hier von vielleicht 10 Anfragen pro Minute, wobei z.B. DAten dann in eine DB geschrieben werden, oder Informationen an den Client zurückgeliefert werden.

Was mich gerade noch etwas verwirrt ist der Ablauf mit RPC. Nehmen wir an, Spring instanziiert bei einer Anfrage eine neue Klasse ("WriteHello" von oben), kann diese dann auch korrekt eine Antwort, also ein Ergebnis zurücksenden (was ja der Rückgabewert der Service-Methode dann ist) und das kommt dann auch beim "richtigen" Client an?

Kann Spring selbständig die Klassen instanziieren bei einer Anfrage, sodass diese dann in einem eigenen Thread die Anfrage abarbeiten, oder ist das Arbeit, die ich "manuell" tun muss?
 
Was mich gerade noch etwas verwirrt ist der Ablauf mit RPC. Nehmen wir an, Spring instanziiert bei einer Anfrage eine neue Klasse ("WriteHello" von oben), kann diese dann auch korrekt eine Antwort, also ein Ergebnis zurücksenden (was ja der Rückgabewert der Service-Methode dann ist) und das kommt dann auch beim "richtigen" Client an?
Ja.

Kann Spring selbständig die Klassen instanziieren bei einer Anfrage, sodass diese dann in einem eigenen Thread die Anfrage abarbeiten, oder ist das Arbeit, die ich "manuell" tun muss?

Vielleicht isses nicht ganz klar geworden. Es braucht nur eine Instanz, solange die eben threadsafe ist. Dann können bequem mehrere Threads auf der einen Instanzarbeiten (daher ja auch der Begriff "threadsafe" ;) ).

Du kannst doch bequem mal mit dem RmiExporter von Spring einen Versuch starten. Hier ist das Beispielprojekt aus meinem Vortrag über Spring bei der Mannheimer Java User Group. Da wird ein Client mit einem Server per RMI verbunden. So ähnlich sollte das ja dann auch bei dir ausschauen. Einfach auschecken und mit Maven bauen. Beschreibung liegt auch dabei.

Gruß
Ollie
 
Ich glaube, ich habe mich bei meinem letzten Post nicht ganz richtig ausgedrückt, das tut mir leid. Was ich eigentlich meinte war, ob Spring selbständig neue Threads aufmacht, um die Anfragen zu bearbeiten.

Also nehmen wir an, wir haben die WriteHello Klasse, welche thread safe ist und es davon nur eine Instanz gibt. Wenn jetzt mehrere Anfragen von verschiedenen Clients kommen, kann Spring es zu handeln, eigenständig Threads aufzumachen, die die Anfragen abarbeiten und die Rückgabe zurücksenden? Oder muss ich diesen Teil manuell umsetzen?
 
Hallo,

wie Oli schon sagte hängt das von der von Spring verwendeten Remoting Technologie ab bzw. deren Integration ab.

Bei Java RMI kann eine Remote Method Invocation in einem (gepooledten) Thread je Client durchgeführt werden muss aber nicht.

Siehe:
http://java.sun.com/javase/6/docs/platform/rmi/spec/rmi-arch3.html

AFAIK verwendet Springs RMIServiceExporter keinen eigenen Threadpool und verlässt sich somit auf die Gegebenheiten der RMI Infrastruktur.

Springs HttpInvokerServiceExporter verlässt sich auf die entsprechende Threading Infrastruktur für Servlets des verwendeten Servlet-Containers.

Die anderen Remoting Facilities (JAX WS, JAX RPC, Hessian, Burlap, JMS, SOAP,caucho, etc.) haben entsprechend ähnliches Threading-verhalten.
Wenn du aus welchen Gründen auch immer dieses verhalten jedoch Ändern wolltest so könntest du dir deine eigene:
org.springframework.remoting.support.RemoteInvocationExecutor Implementierung bauen welche du den entsprechenden RemoteServiceExportern mit gibst.
Standardmäßig gibts davon nur eine Implementierung davon:
http://springframework.cvs.sourcefo...ocationExecutor.java?revision=1.5&view=markup
und die macht einen "synchronen" Aufruf und verlässt sich somit auf das Threadmanagement der zugrundeliegenden Remoting Technologie.

Sorg dafür, dass deine als Remote Service "veröffentlichten" Services Stateless sind und schon hast du auch mit konkurrierenden Aufrufen keine Probleme.

Also nehmen wir an, wir haben die WriteHello Klasse, welche thread safe ist und es davon nur eine Instanz gibt. Wenn jetzt mehrere Anfragen von verschiedenen Clients kommen, kann Spring es zu handeln, eigenständig Threads aufzumachen, die die Anfragen abarbeiten und die Rückgabe zurücksenden? Oder muss ich diesen Teil manuell umsetzen?
Dafür werden (je nach verwendeter Remoting Technolgie) entsprechende Threads aufgemacht. Darum musst du dich also nicht kümmern....

Gruß Tom
 
Vielen Dank für die vielen, sehr hilfreichen Antworten. Ich denke damit habe ich nun den Überblick, den ich benötige.

Wenn ich so darüber nachdenke, was könnte denn im Worst Case passieren? Damit meine ich z.B. den Fall, dass die zugrundeliegende Remoting Technologie (ich verwende Java's RMI) keine Threads selbstständig aufmacht. Würde dann ein 2. Clients bei der Anfrage "abgewiesen" bzw. könnte gar keine Verbindung aufbauen, oder würde seine Anfrage einfach nur erst dann abgearbeitet, wenn die Anfrage davor (vom 1. Client) fertig ist?
 

Neue Beiträge

Zurück