Announcement

Collapse
No announcement yet.

MTS, Singleton und Asynchroneaufrufe

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • MTS, Singleton und Asynchroneaufrufe

    Ich benötige als Einstiegspunkt für eine grosse Anzahl an Usern einen Singleentrypoint.

    Der Hintergrund:
    Wir entwickeln einen Knwoledgemanagement Server, der eine grosse Anzahl von Dokumenten verwalten soll. Da wir durch die Zerlegung der Dokumente in Sätze und Wörter sowie deren Referenzierung untereinander einen hohen Speicherverbrauch haben, ist es unser Ziel alle Objekte genau einmal im Speicher zuhalten. Es ist uns bisher nicht gelungen, MTS dazu zu überreden uns die Objekte als Singleton zu überlassen. Wen wir die Objekte als singleinstance und oder singlethread dekarieren, läuft die Sache mit einem Client sehr gut, sobald der zweite Client sich anmelden will, bekommt er den Einstiegspunkt, aber auf die Objekte die von dort referenziert werden hat er keinen Zugriff.

    Ein zweites Thema sind lang laufende Transaktionen die wir gerne asynchron über MTS abwickeln würden.

    Kennt jemand für diese beiden Aufgabenstellungen Lösungsansätze mit MTS??

    Gruss
    Frank Link

  • #2
    Hallo,

    mit dem MTS und COM+ sind Singleton-Server <b>nicht</b> möglich, da jeder Base Client eine eigene Activity erhält. Wenn das Singleton-Prinzip beibehalten werden soll, muss das Ganze als normaler COM-Server laufen, der seine eigene ClassFactory implementiert

    Comment


    • #3
      Hallo,

      vielen Dank für die Antwort.

      Leider nicht sehr befriedigend. Wir sind darauf angewiesen, dass die Objekte sehr stark untereinander referenzierent arbeiten. Das würde letztendlich bedeuten, dass wir die Arbeit vollständig über die Datenbank abwickeln müssen. Bei den kleinen Informationseinheiten mit denen wir es zu tun haben ist dies viel zu langsam. Als Datenbankserver setzen wir Interbase mit IBX ein.

      <b>Kurze Programmbeschreibung</b>
      Als kleinste Informationseinheit steht bei uns das Wort. Wort referenziert alls Sätze über alle Dokumente. Das Wort ist im System genau einmal vorhanden. Nur so sind wr in der Lage unseren Anwendern ein Informationssystem aufzubauen, dass bei einer Suche alle Wortformen und Synonyme berücksichtigt. Zusätzlich bieten wir verschiedene linguistische Auswertungen über Begriffzusammenhänge. Ein Unternehmen kann sich mit diesem System ein Glossar mit der Unternehmensbegriffen aufbauen (Normsprachenansatz). Das Glossar wird für die Modellierung von dynamischen (EPK) und statischen Aussagen (UML-ClassDiagramm) verwendet (Modellaussagen). Die Modellaussagen werden zur Generierung von Softwarekomponenten verwendet.

      Das als Kurzbeschreibung unserer Anwendung NOAM (Chomsky)

      Sehen Sie vielleicht noch eine andere Lösung um eine extrem skalierbare Intra- / Internet taugliche Anwendung zu erstellen?
      Wenn es nichts anderes gibt müssen wir auf einen althergebrachten HTTP-Server zurückgreifen. In einer Three-Tier Architektur mit einem eigenen Objektcache. Eine sehr arbeitsreiche Lösung.

      Gruss
      Frank Lin

      Comment


      • #4
        Hallo,

        der MTS (COM+) ist immer dann sehr gut, wenn dort zustandslose Objekte ausgeführt werden. Unmittelbar nach dem Ende der aufgerufenen Interface-Methode werden diese Objektinstanzen automatisch zerstört, um beim nächsten Aufruf automatisch wieder zum Leben erweckt zu werden (Just-In-Time-Activation). Dies bedeutet jedoch, dass diese Objekte selbst keine Zustandsdaten speichern können. Es stehen verschiedene Techniken zur Verfügung, um Zustandsdaten trotzdem zwischenzuspeichern: <br>
        1. Der Client speichert die Zustandsdaten und übergibt diese bei jedem Methodenaufruf als Parameter.<br>
        2. Die zustandslosen COM+ Objekte verwenden ein gemeinsames Hilfsobjekt, das Daten in globalen Variablen (Modul) speichert. Auch dann, wenn mit aktiviertem JITA auf dieses Hilfsobjekt zugegriffen wird, teilen sich alle Aufrufer die globalen Daten gemeinsam. <br>
        3. Die zustandslosen COM+ Objekte greifen auf den <i>Shared Property Manager</i> zurück. <br>
        4. Der Base Client greift auf eine globale Variable des COM+ Objekts zu. <br>
        5. Die zustandslosen COM+ Objekte greifen - falls sie aus einer Active Server Page heraus aufgerufen werden - auf die globalen Application-Variablen von ASP zurück.

        Wenn man sich die plausibelsten Alternativen anschaut und die möglichen Implementierungen gegenüberstellt, ergeben sich die folgenden Performance-Ergebnisse:
        <pre>
        Apartment JITA Synchronisierung Zeit in Ticks für 500 Aufrufe
        ------------------------------------------------------------------
        Free Ja Erforderlich 3075
        Free Nein Deaktiviert 3015
        TNA Ja Erforderlich 1041
        TNA Nein Deaktiviert 1032
        nur SPM Ja Erforderlich 151
        globale Var Ja Erforderlich 80
        </pre>
        Neben dem Shared Property Manager ist die globale Variable in der DLL (kein zusätzliches COM+ Hilfsobjekt) ist schnellsten. Allerdings muss man sich dann um die Thread-Abschottung bei den Zugriffen darauf wieder selbst kümmern

        Comment


        • #5
          Hallo Herr Kosch,
          <p>
          wenn ich Ihre Tabelle richtig interpretiere, schlagen Sie vor unser Einstiegsobjekt mit globalen Variablen zu versehen. Die Zugriffssteuerung könnten wir über einen implementierten Mutex entsprechend steuern.
          <p>
          Da alle Schritte, anlegen neuer Objekte, suchen von Objekten über deren ID über diesen zentralen Punkt geschieht, würde dies bedeuten, dass wir nur an dieser Stelle einen theoretischen Engpass hätten, den wir durch geschickte Implementierung umgehen könnten.
          <p>
          Aus meiner Sicht müßten wir lediglich die schreibenden Zugriffe über den Mutex schützen. Alle lesenden Zugriffe (Schleifen etc.) können wir ohne Mutex erlauben, wenn die Counter vorher in lokalen Variablen abgelegt werden.
          <p>
          Da wir den Client und den Server bereits soweit isoliert von einander betreiben können, dass der Client nach Abschluss Arbeit, lediglich seine bearbeiteten Daten an den Server übergibt, müssen wir nur dafür sorgen, dass wir dies asynchron tun können.
          <p>
          Ich habe Ihnen einen Ausschnitt unserer Thread Implementierung begefügt. Sie sehen, dass wir an den Worker zwei Interface-Zeiger übergeben. Bereits bei der Zuweisung der Interface an das eigentliche Worker-Objekt erhalten wir eine Runtime-Exception. Zur Zeit haben wir keine Lösung. Zumal die ganze Sache als reiner DCOM-Server einwandfrei läuft.
          <p>
          TDocumentThread = class( TThread )<br>
          private<br>
          FText : String;<br>
          FDocument : INoamMTSDocument;<br>
          FFactory : INoamMTSFactory;<br>
          protected<br>
          procedure Execute; override;<br>
          public<br>
          constructor Create( const Document : INoamMTSDocument; const Factory : INoamMTSFactory; const Value : String );<br>
          end;<br>
          <p>
          constructor TDocumentThread.Create( const Document : INoamMTSDocument; const Factory : INoamMTSFactory; const Value : String );<br>
          begin<br>
          inherited Create( true );<br>
          FDocument := Document;<br>
          FFactory := Factory;<br>
          FText := Value;<br>
          end;
          <br>
          procedure TDocumentThread.Execute;<br>
          var<br>
          FWorkDocument : INoamWorkDocument;<br>
          ThreadNummber : Integer;<br>
          begin<br>
          ThreadNummber := ThreadForm.addThreadMessage( 'Dokument - wird zerlegt.' );<br>
          try<br>
          CoInitialize( nil );<br>
          FWorkDocument := CoNoamWorkDocument.Create;<br>
          FWorkDocument.Text := FText;<br>
          FWorkDocument.Factory := FFactory;<br>
          FWorkDocument.Document := FDocument;<br>
          FWorkDocument.work;<br>
          finally<br>
          CoUninitialize;<br>
          ThreadForm.removeThreadMessage( ThreadNummber );<br>
          end;<br>
          end;<br>

          Gruss
          Frank Lin

          Comment


          • #6
            Hallo,

            Delphi stellt mit <b>TMultiReadExclusiveWriteSynchronizer</b> bereits einen Mechanismus bereit, um nur die Schreibzugriffe zu koordinieren.
            Das Problem mit der globalen DLL-Variablen liegt nur darin, dass dies ein sehr "flüchtiger" Speicher ist. Wenn kein Client mit der COM+ Anwendung arbeitet und die Timeout-Zeitspanne für das automatische Herunterfahren erreicht wird oder die Anwendung explizit heruntergefahren wird, gehen die Daten verloren. Man benötigt also einen Weg, bei Bedarf hier gegenzusteuern.

            Generell ist es beim MTS/COM+ keine gute Idee, eigene Threads aus den COM-Objekten heraus abzuspalten. Statt dessen sollte man auf den automatischen Thread-Pool vertrauen und bei Bedarf nur zusätzliche Objektinstanzen anfordern (die vom MTS/COM+ in einem eigenen Thread ausgeführt werden). Die Parallelität erreicht man also durch die Implementierung als separate Objekte.

            Auf der Client-Seite sind mehrere Threads jedoch kein Problem. Wenn der Thread beim Erzeugen über Create bereits "scharfe" Interface-Zeiger erhält, ist das in Ihrer Implementierung nur dann ohne spezielle Vorbehandlung legal, wenn alle Objekte im gleichen Apartment laufen (genauer gesagt müssen alle als MTA implementiert werden und auch der Aufrufprozess muss ein MTA anmelden). Der üblichere Weg (und für die VCL der stabilere Weg) besteht jedoch darin, von STA-Objekten auszugehen und die Interface-Zeiger entsprechend vorzubereiten: <br>
            a) <b>CoMarshalInterThreadInterfaceInStream</b> bereitet im primären Thread den Interface-Zeiger so vor, dass er als Parameter für Create (TThread) verwendet werden darf. <br>
            b) <b>CoGetInterfaceAndReleaseStream</b> sorgt in Execute (TThread) dafür, dass der Marshaler eine legale Brücke zu dieser Objektinstanz baut

            Comment


            • #7
              Hallo Herr Koch,
              <p>
              ich habe heute Ihr Buch erhalten, finde ich in diesem entsprechende Hinweise zu diesen Funktionen und ihre Anwendung?
              <p>
              Ich komme jetzt an meine eigenen Wissensgrenzen im Umgang mit COM/COM+ da ich persönlich aus der Corba-Ecke komme. Wir haben uns für COM+ lediglich aus Lizenzgründen entschieden.
              <p>
              Können Sie, mir die Seiten in Ihrem Buch nennen, bzw. die Implementierung die ich im vorhergehenden Kommentar angehangen habe so ändern, dass es theoretisch funktionieren müßte?
              <p>
              Die Instanz des Threads wird übrigens auf Client-Seite gestartet.
              <p>
              Gruss
              <p>
              Frank Lin

              Comment


              • #8
                Hallo,

                in meinem <i>COM/DCOM/COM+ mit Delphi</i>-Buch sind die folgenden Kapitel relevant: <br>
                - Kapitel 4 <i>Marshaler und Apartments</i> (69 Seiten) <br>
                - Kapitel 15 <i>MTS</i> <br>
                - Kapitel 16 <I>COM+</i> (baut auf Kapitel 15 auf)<br>
                Auf der CDROM sind mehrere Beispielprojekte, die den Zugriff auf Interface-Zeiger aus separaten Threads heraus demonstrieren. Ich würde vor eigenen Versuchen in jedem Fall das Kapitel 4 vollständig lesen

                Comment


                • #9
                  Hallo Herr Kosch,

                  vielen Dank ersteinmal. Ich melde mich in den nächsten Tagen.

                  Gruss und schönes Wochenende

                  Frank Lin

                  Comment


                  • #10
                    Hallo Herr Kosch,
                    <p>
                    das Lesen von Kapitel 4 hat ausgereicht, um eine asynchrone Kommunikation mit einem MTS-Objekt aufzubauen. Ich brauchte lediglich den Code für den Thread etwas zu ändern.
                    <p>
                    procedure TDocumentThread.Execute;<br>
                    var<br>
                    ThreadNummber : Integer;<br>
                    FWorkDocument : INoamWorkDocument;<br>
                    begin<br>
                    OleCheck( CoInitialize( nil ) );<br>
                    ThreadNummber := ThreadForm.addThreadMessage( 'Dokument - wird zerlegt.' );<br>
                    try<br>
                    OleCheck( CoGetInterfaceAndReleaseStream( FStream, IID_INoamWorkDocument, FWorkDocument ) );<br>
                    FWorkDocument.work( ThreadNummber );<br>
                    finally<br>
                    CoUninitialize;<br>
                    ThreadForm.removeThreadMessage( ThreadNummber );<br>
                    FStream := nil;<br>
                    end;<br>
                    end;<br>
                    <p>
                    Wichtig war vor allem, das alle Zuweisungen an das MTS-Workerobject ausserhalb des Threads erfolgten.<br>
                    <p>
                    procedure TDocumentForm.acSendSequenceExecute(Sender: TObject);<br>
                    var<br>
                    FWorkDocument : INoamWorkDocument;<br>
                    Stream : IStream;<br>
                    Thread : TDocumentThread;<br>
                    begin<br>
                    acSendSequence.Enabled := false;<br>
                    TEditorDocumentForm(EditorPanel.Form).Editor.SelAt tributes.BkColor := clYellow;<br>
                    Text := TEditorDocumentForm(EditorPanel.Form).Editor.SelTe xt;<br>

                    FWorkDocument := CoNoamWorkDocument.Create;<br>
                    FWorkDocument.Document := FDocument;<br>
                    FWorkDocument.Factory := FFactory;<br>
                    FWorkDocument.Text := Text;<br>

                    OleCheck( CoMarshalInterThreadInterfaceInStream( IID_INoamWorkDocument, FWorkDocument, Stream ) );<br>
                    Thread := TDocumentThread.Create( Stream );<br>
                    Thread.Resume;<br>
                    end;<br>
                    <p>
                    Seit dem ich den Code so umgestellt habe, läuft der Aufruf auch dann, wenn ich in der Anwendung mehrere von diesen Threads parallel laufen habe.<br>
                    <p>
                    Zusammen, mit der eventfunktionalität, die ich mir bei techvanguards.com herutergeladen habe, konnte ich meine gewünschte Funktionalität ziemlich sauber realisieren.<br>
                    <p>
                    Wir sind zwar nach wie vor nicht in der Lage den von unsgewünschten Zentralen ObjectCache aufzubauen, aber die Observer / Obserable Funktionen über vertelte Applikationen funktioniert.<br>
                    <p>
                    Nochmals vielen Dank für die Hilfe.<br>
                    <p>
                    Frank Lin

                    Comment

                    Working...
                    X