AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Webserveranwendung: EXE ruft ISAPI
Thema durchsuchen
Ansicht
Themen-Optionen

Webserveranwendung: EXE ruft ISAPI

Ein Thema von Delbor · begonnen am 22. Aug 2014 · letzter Beitrag vom 25. Aug 2014
Antwort Antwort
Seite 2 von 3     12 3      
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#11

AW: Webserveranwendung: EXE ruft ISAPI

  Alt 23. Aug 2014, 22:43
Hi Olli73

Zitat:
Nö. Wenn die ISAPI einmal geladen ist, verbleibt sie normalerweise im Speicher; es sei denn du setzt absichtlich den Registryeintrag "CacheExtensions" auf 0:
Ups! Ich habe da zwar - von Embaecadero - andere Infos:
Jede Anforderung wird in einem eigenen Thread behandelt.

Ich habe jetzt doch eine Weile gesucht und bislang nur oben verlinkte Seite gefunden, die meine Aussage unterstützt.
Aber vielleicht sollten ich doch mal ein Missverständnis ausräumen: Ich wollte nicht behaupten, dass die dll aus dem Speicher entfernt wird:
Zitat:
Eine Webbrokeranwendung (Isapi) wird genau für jeweils einen Request ausgeführt, beantwortet diesen und wird dann beendet
Das stimmt so wirklich nicht. Es geht darum, dass ISAPI für jeden Request einen Thread startet - und dieser wird beendet, wenn die Anfrage fertig bearbeitet ist.

Zitat:
Globale Variablen sind grundsätzlich Pfui, da multithreaded, und müssen durch critical sections abgesichert werden. Aber als globale Variable brauchst du eigentlich nur eine SessionList (Liste, Array, Hashmap, ...). Diese ist durch eine CriticalSection abzusichern.

In die einzelnen Sessions (Session-Objekte) kannst du dann deine Daten, (Daten-)Objekte, Datenmodule etc. packen. Dabei muss ein Objekt oder Datenmodul für jede Session neu erstellt werden und es dürfen auch dort keine globalen Variablen, sondern nur Felder/Properties verwendet werden.
Es ist jetzt schon eine Weile her, dass ich selbst mit Threads gearbeitet habe. Was mir davon so aus dem Stegreif noch geblieben ist: ein Thread eines (Desktop-)Programmes kann nicht auf ein VCL-Objekt zugreifen, ausser durch Synchronisierung. Das aber kann den Performancevorteil eines Threads zunichte machen. Ein (Session-)Objekt müsste also dem Thread vor/beim Start übergeben werden.

Ich hab jetzt gerade noch etwas in den Sourcen gestöbert. Bislang hatte ich geglaubt, durch die Verwendung der Isapi-Units, die Delphi mitliefert, würde ein Thread automatisch gestarte, konnte bislang aber keinen Code finden, der sowas macht...
Solche Aussaggen veranlassten mich zu dieser Annahme:
Na ja, mir schwant, dass ein ausführliches Studium zuverlässiger als die Embarcadero-Help ist...

Andrerseits - was ist eigentlich genau die Aufgabe der IIS? Sorgen die für den ThreadStart? Da sind leider keine Sourcen dabei, wo man selbst nachsehen könnte, was genau abläuft.

Das mit den globalen Variablen war mir bekannt: Das war für mich einer, wenn nicht gar der Hauptgrund, für eine EXE.


Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
Benutzerbild von Olli73
Olli73

Registriert seit: 25. Apr 2008
Ort: Neunkirchen
662 Beiträge
 
#12

AW: Webserveranwendung: EXE ruft ISAPI

  Alt 24. Aug 2014, 01:51
Zitat:
Nö. Wenn die ISAPI einmal geladen ist, verbleibt sie normalerweise im Speicher; es sei denn du setzt absichtlich den Registryeintrag "CacheExtensions" auf 0:
Ups! Ich habe da zwar - von Embaecadero - andere Infos:
Jede Anforderung wird in einem eigenen Thread behandelt.

Ich habe jetzt doch eine Weile gesucht und bislang nur oben verlinkte Seite gefunden, die meine Aussage unterstützt.
Da steht "eigner Thread". Und das ist korrekt. Aber es ist immer nur ein Prozess und daher ist es auch ein gemeinsamer Speicherbereich. Man muss lediglich mit den Speicherzugriffen aufpassen (kritische Abschnitte verwenden).

Zitat:
Aber vielleicht sollten ich doch mal ein Missverständnis ausräumen: Ich wollte nicht behaupten, dass die dll aus dem Speicher entfernt wird:
Zitat:
Eine Webbrokeranwendung (Isapi) wird genau für jeweils einen Request ausgeführt, beantwortet diesen und wird dann beendet
Das stimmt so wirklich nicht. Es geht darum, dass ISAPI für jeden Request einen Thread startet - und dieser wird beendet, wenn die Anfrage fertig bearbeitet ist.
Ich bin mir jetzt nicht sicher, wie es bei ISAPI ist, aber wenn du eine "Webbroker-EXE" erstellst, gibt es einen Thread-Pool, d.h. es gibt auch dort mehrere Threads, die werden aber nicht sofort beendet, sondern werden der nächsten Anfrage (eines beliebigen Clients!) erneut zugeteilt. Macht daher letztlich keinen Unterschied, da der Client/Browser bei jeder Anfrage in einem anderen Thread landen kann. Wenn du also z.B. im Webmodul ein Dataset offen lässt, greift später ggf. ein ganz anderer Client auf dieses zu.

Zitat:
Zitat:
Globale Variablen sind grundsätzlich Pfui, da multithreaded, und müssen durch critical sections abgesichert werden. Aber als globale Variable brauchst du eigentlich nur eine SessionList (Liste, Array, Hashmap, ...). Diese ist durch eine CriticalSection abzusichern.
In die einzelnen Sessions (Session-Objekte) kannst du dann deine Daten, (Daten-)Objekte, Datenmodule etc. packen. Dabei muss ein Objekt oder Datenmodul für jede Session neu erstellt werden und es dürfen auch dort keine globalen Variablen, sondern nur Felder/Properties verwendet werden.
Es ist jetzt schon eine Weile her, dass ich selbst mit Threads gearbeitet habe. Was mir davon so aus dem Stegreif noch geblieben ist: ein Thread eines (Desktop-)Programmes kann nicht auf ein VCL-Objekt zugreifen, ausser durch Synchronisierung. Das aber kann den Performancevorteil eines Threads zunichte machen. Ein (Session-)Objekt müsste also dem Thread vor/beim Start übergeben werden.
Da du hier eh nicht mit visuellen Komponenten arbeiten kannst, macht es das schon mal etwas einfacher. Das Synchronize wird meist benutzt, um die Oberfläche/Forms anzupassen, das entfällt ja hier. Ansonsten benötigst du eigentlich nur eine globale Variable (oder besser eine Function oder noch besser eine Klassenmethode) mit einer "SessionList" über die du an ein bestimmtes Datenobjekt oder eine bestimmte Instanz eines Datenmoduls herankommst. Die Sessionlist und ggf. das Datenobjekt/Datenmodul musst du mit einer CriticalSection absichern, damit eben sicher gestellt ist, dass sich die Threads nicht in die Quere kommen. Wenn du mit Datenbanken arbeitest, musst du auch pro Session eine Datenbankverbindung aufbauen, wenn deine Datenbank-Connection-Komponente nicht explizit als Threadsafe gekennzeichnet ist.

Wenn also eine neue Anfrage in deinem Webmodul landet, musst du zuerst über die sessionList (unter Beachtung der CriticalSection!) aufrufen und dir darüber deine Daten für diese Session besorgen, bzw. einen neuen Eintrag in der Liste anlegen und eine neue Instanz der Datenstruktur erstellen, wenn es eine neue Session ist (der Client benötigt dann auch diese Session-ID und muss die beim nächsten mal mitsenden).

Zitat:
Ich hab jetzt gerade noch etwas in den Sourcen gestöbert. Bislang hatte ich geglaubt, durch die Verwendung der Isapi-Units, die Delphi mitliefert, würde ein Thread automatisch gestarte, konnte bislang aber keinen Code finden, der sowas macht...
Das passiert AFAIK irgendwo (tief) in den Indy-Komponenten.

Stimmt ja auch, ABER (s.o.): Thread != Prozess

Zitat:
Na ja, mir schwant, dass ein ausführliches Studium zuverlässiger als die Embarcadero-Help ist...
Waren scheinbar nur die Begrifflichkeiten. Aber sowas passiert mir in anderen Fällen auch ständig.

Zitat:
Das mit den globalen Variablen war mir bekannt: Das war für mich einer, wenn nicht gar der Hauptgrund, für eine EXE.
Da hilft dir eine "Webbroker-EXE" aber auch nicht weiter, da es dort das Gleiche mit den Threads ist (s.o.). Und ein CGI ist sogar ein eigener Prozess, also noch weniger für dich geeignet.


Gruß,
Olli
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#13

AW: Webserveranwendung: EXE ruft ISAPI

  Alt 24. Aug 2014, 13:20
Hi Olli
Zitat:
Da hilft dir eine "Webbroker-EXE" aber auch nicht weiter, da es dort das Gleiche mit den Threads ist (s.o.). Und ein CGI ist sogar ein eigener Prozess, also noch weniger für dich geeignet.
Die Webbroker-Anwendung befindet sich nach wie vor in einer eigenen Datei - eben der DLL, wie sie von Delphi erstellt wird. Die exe ist eine normale Form, zur Zeit ohne jegliche visuellen Komponenten.
Die wohl wichtigste Klasse ist hier TIdWebbrokerBriodge, über die die Webbroker-Anwendung, bzw die erzeugte dll, aufgerufen wird - aber deswegen wohl die Apostrophe.

Zitat:
Da du hier eh nicht mit visuellen Komponenten arbeiten kannst, macht es das schon mal etwas einfacher.
Soweit ich dies in Erinnnerung habe, ist ein Synchronize immer dann nötig, wenn auf eine Klasse zugegriffen werden soll, die im Hauptthread abläuft, ob sie nun visuell ist oder nicht.

Mein vorheriges Projekt war eine Bilderdatenbank. Für die hatte ich eine Klasse erstellt, die die Daten aus einer SQL-Anfrage übernimmt (ein DS pro Instanz). Dasselbe gedachte ich eigentlich hier zu realisieren. Kurz skizziert:
  • eine Klasse wird von TThread abgeleitet(TCustomThrread?)
  • Die Klasse erhält(Stream-)Felder, für jedes DB-Feld eines. Ein 'Speicherzugriff' ist somit nach dem Start nur innerhalb des Threads nötig.

Aber bevor ich das realisiere, muss ich mir über den genauen Ablauf klar werden - wenn nämlich der Isapi-Tread entegegen meiner bisherigeen Erkenntnis trotzdem automatisch gestartet wird, wird es... na ja, sagen wir mal: interessant.

Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#14

AW: Webserveranwendung: EXE ruft ISAPI

  Alt 24. Aug 2014, 13:31
@Delbor

Ein Synchronize ist eigentlich nur für die GUI notwendig. Alles andere kann man über die Synchro-Objekte so steuern, dass immer nur ein Thread-Kontext gleichzeitig zugreift (zugreifen kann)

Zudem wiegt man sich mit dem Synchronize auch in eine falsche Sicherheit.

Also erstelle die gemeinsam genutzten Klassen threadsafe und benutze die einfach (ohne Synchronize)
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#15

AW: Webserveranwendung: EXE ruft ISAPI

  Alt 24. Aug 2014, 14:36
Hi Sir Rufo

Laut Help gilt das mit der falschen Sicherheit für CriticalSections ebenso wie für Synchronize. Ich denke mir, eine CriticalSection beim Create des Threads und bestücken seiner Felder sollte ausreichen, da der Thread zu seiner Laufzeit nur auf seinen eigenen Speicherbereich zugreift.

Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#16

AW: Webserveranwendung: EXE ruft ISAPI

  Alt 24. Aug 2014, 14:55
Wenn du bei einem Thread von aussen die Felder bestücken kannst, dann hast du den Thread absolut falsch aufgebaut.

Von aussen sollte man mit dem Thread ausschliesslich über Methoden und Eigenschaften kommunizieren können. Diese kann man zuverlässig mit den SynchroObjekten threadsafe gestalten.

Eigentlich ist es ganz einfach: Man sorgt dafür, dass es nicht möglich ist auf einen Speicherbereich mit unterschiedlichen Threads gleichzeitig zuzugreifen.

Wenn man das mit Synchronize versucht (im MainThreadKontext), dann muss man höllisch aufpassen, dass jeder Zugriff darauf per Synchronize erfolgt (hört sich irgendwie schon komisch an).

... eine CriticalSection beim Create des Threads und bestücken seiner Felder sollte ausreichen, da der Thread zu seiner Laufzeit nur auf seinen eigenen Speicherbereich zugreift.
hmmm, wenn du innerhalb des Konstruktors die Felder setzt und auf die von aussen (über Eigenschaften, Methoden) nicht zugegriffen wird, dann brauchst du gar keine CriticalSection.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (24. Aug 2014 um 15:02 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Olli73
Olli73

Registriert seit: 25. Apr 2008
Ort: Neunkirchen
662 Beiträge
 
#17

AW: Webserveranwendung: EXE ruft ISAPI

  Alt 24. Aug 2014, 15:11
Hi Sir Rufo
Ich denke mir, eine CriticalSection beim Create des Threads und bestücken seiner Felder sollte ausreichen, da der Thread zu seiner Laufzeit nur auf seinen eigenen Speicherbereich zugreift.
2 "Denkfehler" in 1 Satz:

(1) Der Thread hat keinen "eigenen Speicherbereich", es gibt nur 1 gemeinsamen Speicherbereich für den gesamten Prozess; das "getrennt" zu halten bzw. gegenseitige Zugriffe in sicherer Weise zu erlauben ist deine Aufgabe.

(2) Die CriticalSection musst du vor jedem Zugriff betreten und anschließend wieder verlassen und zwar aus dem Thread heraus, der auf die Daten zugreifen will; so wird der gleichzeitige Zugriff von 2 Threads aus verhindert. Das ist aber auch der Grund, warum die CriticalSection dir bei GUI-Komponenten nichts bringt: Da die VCL/WinApi deine CriticalSection nicht kennt, wird sie sie auch nicht beachten.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#18

AW: Webserveranwendung: EXE ruft ISAPI

  Alt 24. Aug 2014, 15:21
Das ist aber auch der Grund, warum die CriticalSection dir bei GUI-Komponenten nichts bringt: Da die VCL/WinApi deine CriticalSection nicht kennt, wird sie sie auch nicht beachten.
Ähm, nee, das ist anders.

Die VCL ist nicht threadsafe ausgelegt und darum darf man auf die VCL-Teile eben nur synchronisiert zugreifen. Der andere Weg ist doch simpel über Getter und Setter zu erreichen, die dann die CriticalSection betreten und wieder verlassen.

Irgendwie beschleicht mich das Gefühl, dass hier von einer globalen CriticalSection gesprochen wird ... ist dem so, oder kommt nur meine Paranoia wieder hoch?
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Benutzerbild von Olli73
Olli73

Registriert seit: 25. Apr 2008
Ort: Neunkirchen
662 Beiträge
 
#19

AW: Webserveranwendung: EXE ruft ISAPI

  Alt 24. Aug 2014, 15:38
Das ist aber auch der Grund, warum die CriticalSection dir bei GUI-Komponenten nichts bringt: Da die VCL/WinApi deine CriticalSection nicht kennt, wird sie sie auch nicht beachten.
Ähm, nee, das ist anders.

Die VCL ist nicht threadsafe ausgelegt und darum darf man auf die VCL-Teile eben nur synchronisiert zugreifen. Der andere Weg ist doch simpel über Getter und Setter zu erreichen, die dann die CriticalSection betreten und wieder verlassen.
Ich habe mich da falsch ausgedrückt; ich meinte eigentlich, das es nicht ausreicht, wenn man jetzt auf den Gedanken kommt einfach selbst immer vor einem Zugriff auf ein VCL-Objekt eine CriticalSection zu betreten. Dann wären zwar die eigenen Zugriffe abgesichert, aber nicht die von der VCL/WinAPI...

Zitat:
Irgendwie beschleicht mich das Gefühl, dass hier von einer globalen CriticalSection gesprochen wird ... ist dem so, oder kommt nur meine Paranoia wieder hoch?
Also ich spreche die ganze Zeit nur von einer CriticalSection für eine "SessionList" und ggf. je einer CriticalSection pro "Datenobjekt" (welches in dieser Liste verwaltet wird).
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#20

AW: Webserveranwendung: EXE ruft ISAPI

  Alt 24. Aug 2014, 16:32
Hi zusammen

Ich sehe das bisher so vor :
  1. Die Anfrage kommt rein
  2. Sie wird analysirtte
  3. In der Sessionlist wird geprüft, ob für den Anfrager bereits eine Session Existiert. Ein Datenbankzugriff ist hier nicht nötig, da die DB nur Infos über geschlossene Sessions enthält.
  4. Gibt es keine Session, wird eine neu erstellt - auchh für anonyme User.
  5. Gemäss der Anfrage wird die DB abgefragt. Die enthält u.a. Felder zum
    • URL
    • HTML
    • CSS
    • MenueCSS
  6. Das Resultat wird an Klassenfelder verteilt, die den Tabellenfeldern entsprechen. Diese Klasse Marke Eigenbau ist ein Proberty einer eigenen Threadklasse
  7. Der Thread wird erstellt und die Isapi gestartet

Zitat:
(2) Die CriticalSection musst du vor jedem Zugriff betreten und anschließend wieder verlassen und zwar aus dem Thread heraus, der auf die Daten zugreifen will;
Wenn eine CriticalSection 'nur' den Datenbereich sperrt, auf die der Thread, der sie einsetzt, zugreifen will, brauchts wirklich keine, immer vorausgesetzt, die Parameter Requestinfo, ResponseInfo und Co. haben keine Verbindung nach aussen und sind eigene Instanzen der jeweilgen Klassen.

Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 2 von 3     12 3      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:40 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz