AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke WebModule & ADOConnection in Service -> Speicherübrelauf
Thema durchsuchen
Ansicht
Themen-Optionen

WebModule & ADOConnection in Service -> Speicherübrelauf

Ein Thema von markusef · begonnen am 13. Jan 2017 · letzter Beitrag vom 19. Jan 2017
Antwort Antwort
Seite 1 von 2  1 2      
nahpets
(Gast)

n/a Beiträge
 
#1

AW: WebModule & ADOConnection in Service -> Speicherübrelauf

  Alt 13. Jan 2017, 14:56
Meckert Delphi auch noch, wenn Du die beiden Co...Dingens ins Create bzw. Destroy packst?

Bei mir (mit Delphi 7) gab es von Delphi immer schimpfe, wenn ich es nicht bei "initialization" und "finalization" reingepackt hatte, sondern sonstwo.

Habe Webmodule nur in DLLs und CGIs für meinen Webserver genutzt. Ob das in 'nem Service nicht nutzbar ist, weiß ich nicht.
Aber eigentlich ist Dein Service doch das gleiche wie 'ne Exe plus DLL in "eins zusammengepackt"

Beim fünften mal Lesen Deines Quelltextes fiel mir was auf, weiß aber nicht, ob das Problem daher kommen könnte:

Auf ein ADOQuery.Open folgt kein ADOQuery.Close.
  Mit Zitat antworten Zitat
markusef

Registriert seit: 9. Mai 2016
15 Beiträge
 
Delphi 10 Seattle Professional
 
#2

AW: WebModule & ADOConnection in Service -> Speicherübrelauf

  Alt 13. Jan 2017, 15:07
Also anscheinend wird beim erstmaligen verbinden eine Instanz von TWebModule angelegt, danach (vorerst) keine weitere. Ich habe einen Testclient gebaut welcher eine Anfrage schickt, auf ein Response wartet und wenn ein Response ankam gleich den nächsten Request abschickt. Dann rutschte er zu Beginn zwei mal in die WebModuleCreate und anschließend lief alles im Alleingang (hatte beim Debugen nur einen Haltepunkt in der Create und in der Destroy), Destroy wurde auch erst bei Beendigung des kompletten Services ausgeführt.
Irgendwas ist da mächtig Faul

CoInitialize(nil) und CoUnitialize war auch mein nächster Tipp im Create, das funktioniert auch, komischerweise aber nur bis zu einem bestimmten Punkt, ab einer gewissen Anzahl von Anfragen wirft er mir plötzlich trotzdem eine Exception das CoInitialize nicht aufgerufen wurde.

ADOQuery.Close verhalf leider auch nicht zum gewünschten Erfolg :-/
Markus
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#3

AW: WebModule & ADOConnection in Service -> Speicherübrelauf

  Alt 13. Jan 2017, 15:38
Das wird jetzt irgendwie etwas seltsam:

Jetzt kommt von mir mal nur vermuteter Spekulatius ohne Gewähr.

Meine mal gelesen zu haben, dass pro Client ein Webmodul erstellt wird. Also müsste pro Client auch einmal Create aufgerufen werden.

Bei der Verwendung von HTTP können (meine ich jedenfalls) zwischen einem Client und einem Server zwei Verbindungen aufgebaut werden. Dies würde das zweimalige Aufrufen von Create bei Nutzung eines Testclients erkären.

Was passiert, wenn Du den Testclient mehrfach startest. Erhöht sich die Anzahl der Create-Aufrufe dann?

Wenn ja, dann packe die ADOQuery mal auf das Webmodule, statt sie bei 'ner Anfrage selbst zu erstellen und wieder freizugeben.

Wird das Webmodule pro Client erstellt, dürfte es dann auch (kaum) zu Konflikten kommen, wenn mehrere Anfragen unterschiedlicher Clients zeitgleich beim Service ankommen.

Das mit dem CoIni-Dingens kann ich (nicht) verstehen.

Wenn das für die ganze Applikation gilt, dürfte bei wiederholten Anforderungen an den Service mit jeweiligen Aufrufen von CoInitialize und CoUninitialize und gleichzeitigen Anfragen mehrere Clients hier ein bisserl "Durcheinander" entstehen. Es ist ja nicht sichergestellt, dass die Anfragen vollständig nacheinander "abgearbeitet" werden.

Habe bei meinen ISAPI-Dlls erst dann Ruhe gehabt, nachdem ich die Aufrufe nach initialization bzw. finalization verschoben hatte.

Mal noch 'ne andere Idee:

Kannst Du die beiden Aufrufe nicht irgendwo außerhalb des Webmoduls im Service unterbringen?

Oder, nachdem ich mal in alte Quellen geguckt habe, in der DPR zu eine ISAPI-Dll steht dashier:
Delphi-Quellcode:
library WebSQLSearch;

uses
  ActiveX,
  ComObj,
  ISAPIThreadPool,
  ISAPIApp,
  BrkrConst in '..\..\..\Delphi7\Source\Internet\BrkrConst.pas',
  WebBroker in '..\..\..\Delphi7\Source\Internet\WebBroker.pas',
  WebSQLSearchUnit1 in 'WebSQLSearchUnit1.pas{wm: TWebModule};

{$R *.res}

exports
  GetExtensionVersion,
  HttpExtensionProc,
  TerminateExtension;

begin
  CoInitFlags := COINIT_MULTITHREADED; // <--- Hast Du das irgendwo untergebracht?
  Application.Initialize;
  Application.CreateForm(Twm, wm);
  Application.Run;
end.
Eventuell bekommst Du das Problem ja dann hiermit weg:
Delphi-Quellcode:
initialization
  CoInitFlags := COINIT_MULTITHREADED;
  CoInitialize(nil);

finalization
  CoUninitialize;

end.
  Mit Zitat antworten Zitat
HolgerX

Registriert seit: 10. Apr 2006
Ort: Leverkusen
985 Beiträge
 
Delphi 6 Professional
 
#4

AW: WebModule & ADOConnection in Service -> Speicherübrelauf

  Alt 13. Jan 2017, 18:20
Hmm..

Hab noch kein Webmodul erstellt, also in blaue...

Wenn dein

getNothing(

in seinem eignen Thread aufgerufen wird, dann muss immer das CoInitialize und das CoUninitialize im getNothing( gemacht werden, sprich da , wo mit den ADOs gearbeitet wird!

Jeder Thread muss sein eigenes CoInitialize machen, deshalb geht das (globale) CoInitialize im Initialization nicht.
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#5

AW: WebModule & ADOConnection in Service -> Speicherübrelauf

  Alt 13. Jan 2017, 18:28
Mein praktische Erfahrung mit dutzenden von ISAPI-Dlls ist bisher: Es geht nur, wenn es so
Delphi-Quellcode:
initialization
  CoInitialize(nil);

finalization
  CoUninitialize;

end.
gemacht wurde und in der DPR die erste Zeile hinter dem begin   CoInitFlags := COINIT_MULTITHREADED; lautet.

Habe jedenfalls in meinem Fundus keine funktionierende ISAPI-Dll bzw. kein funktionierendes CGI-Programm, die/das ADO nutzt und der Aufruf anders geregelt ist.
  Mit Zitat antworten Zitat
Benutzerbild von Olli73
Olli73

Registriert seit: 25. Apr 2008
Ort: Neunkirchen
792 Beiträge
 
#6

AW: WebModule & ADOConnection in Service -> Speicherübrelauf

  Alt 15. Jan 2017, 13:31
Also anscheinend wird beim erstmaligen verbinden eine Instanz von TWebModule angelegt, danach (vorerst) keine weitere. Ich habe einen Testclient gebaut welcher eine Anfrage schickt, auf ein Response wartet und wenn ein Response ankam gleich den nächsten Request abschickt. Dann rutschte er zu Beginn zwei mal in die WebModuleCreate und anschließend lief alles im Alleingang (hatte beim Debugen nur einen Haltepunkt in der Create und in der Destroy), Destroy wurde auch erst bei Beendigung des kompletten Services ausgeführt.
Irgendwas ist da mächtig Faul
Da ist nix faul. Es wird ein Pool von WebModule-Instanzen erstellt: Bei mehreren gleichzeitigen Anfragen, werden neue Instanzen erstellt, die bleiben dann auch erhalten und jede neue Anfrage wird an eine dieser Instanzen geschickt.

CoInitialize(nil) und CoUnitialize war auch mein nächster Tipp im Create, das funktioniert auch, komischerweise aber nur bis zu einem bestimmten Punkt, ab einer gewissen Anzahl von Anfragen wirft er mir plötzlich trotzdem eine Exception das CoInitialize nicht aufgerufen wurde.
CoInitialize sollte nur 1 mal zu Beginn aufgerufen werden. Daher nicht im Create des Webmodule aufrufen, da das ja mehrfach geschehen kann.
  Mit Zitat antworten Zitat
markusef

Registriert seit: 9. Mai 2016
15 Beiträge
 
Delphi 10 Seattle Professional
 
#7

AW: WebModule & ADOConnection in Service -> Speicherübrelauf

  Alt 16. Jan 2017, 08:12
Hallo,

erstmal danke für die zahlreichen Antworten, ich war am Wochenende leider nicht da.
Also das Flag wurde gesetzt (CoInitFlags := COINIT_MULTITHREADED) in der ersten Zeile unterhalb von 'begin' in der der dpr.
Weiterhin wurde CoInitialize(nil) und CoUninitialize nochmals in 'initialization' & 'finalization' eingefügt. Starte ich den Service nun, wirft er mir bei der Nutzung der ADO eine Exception das CoInitialize nicht verwendet wurde.

Das Speicherüberlauf-Problem ist leider immer noch vorhanden, an der rohen TWebModule Instanz kann es nicht liegen, lasse ich (testweise) die Verbindung zur DB sein und kommentiere diese aus, dann kann ich locker 2000 Anfragen in ein paar Sekunden stellen ohne das der Arbeitsspeicher auch nur mit der Wimper zuckt. Demnach muss es irgendwas mit der ADO Connection zu tun haben.

Ich würde ja auch eine andere DB Verbindungsart testen, weis aber ehrlich gesagt bei einer MaxDB (SAP) nicht was ich sonst für eine Verbindung nutzen kann, zumal ich bisher mit der ADOConnection sehr gut gefahren bin.

@nahpets: wenn ich weitere Instanzen des Clients starte (auf der selben Maschine) dann wird keine neue Verbindung erstellt, ich denke mal du wirst recht haben mit den zwei Verbindungen. Habe ich drei bis vier Instanzen offen bekomme ich auch Exceptions das dass Datenbankobjekt mehrfach genutzt wird, demnach stimmt die Theorie soweit das er pro IP/Client ein WebModule erstellt da ja in diesem Fall mehrere Clients ein WebModule "genutzt" haben.
Markus

Geändert von markusef (16. Jan 2017 um 08:20 Uhr)
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#8

AW: WebModule & ADOConnection in Service -> Speicherübrelauf

  Alt 16. Jan 2017, 11:48
oder nur?

CoInitialize(nil) und CoUninitialize dürfen nur einmalig aufgerufen werden. Nicht pro Verbindung und nicht pro Client und nicht pro Anfrage, sondern insgesamt nur einmal.

Bei 'ner ISAPI-Dll ist das durch den Aufruf in initialization und finalization sichergestellt. Weiß nicht, ob das bei 'nem Service auch so ist, würd' es aber doch stark vermuten. Schlimmstenfalls mal bei jedem Aufruf der beiden Routinen 'nen Eintrag in 'ne Logdatei machen, um so zu prüfen, wie oft man da vorbeikommt.

Alternative:
Delphi-Quellcode:
begin
  CoInitFlags := COINIT_MULTITHREADED;
  CoInitialize(nil);
  Application.Initialize;
  Application.CreateForm(Application.CreateForm(Twm, wm);
  Application.Run;
  CoUninitialize;
end.
Ich vermute mal, dass CoInitialize da nicht so ganz threadsave ist, da die Aufrufe ja allem Anschein nach weitere Verbindungen irgendwie beeinflussen.

Wenn alle Stricke reißen, dann mal die ganze Verbindung von CoInitialize über Verbindung zur Datenbank und Ausführung der Abfrage, bis CoUninitialize mit 'ner TCriticalSection kapseln. Allerdings scheint mir das dann nicht so wirklich im Sinne des Erfinders zu sein.

Eventuell findest Du hier ja weitere Hinweise: https://www.benefind.de/web.php?org=...+thread+delphi

Hab' mal die Sourcen einer funktionierenden ISAPI-Dll angehängt, eventuell kannst Du damit ja was anfangen.

Geändert von nahpets (21. Nov 2017 um 16:41 Uhr)
  Mit Zitat antworten Zitat
markusef

Registriert seit: 9. Mai 2016
15 Beiträge
 
Delphi 10 Seattle Professional
 
#9

AW: WebModule & ADOConnection in Service -> Speicherübrelauf

  Alt 16. Jan 2017, 13:24
Alternative:
Delphi-Quellcode:
begin
  CoInitFlags := COINIT_MULTITHREADED;
  CoInitialize(nil);
  Application.Initialize;
  Application.CreateForm(Application.CreateForm(Twm, wm);
  //Initialisierungen hier zwischen...
  Application.Run;
  CoUninitialize;
end.
Funktioniert so leider auch nicht. Bekomme dann die Exception das CoInitialize nicht aufgerufen wurde.

Die Initialisierung des Webmodules erfolgt in der .dpr:

Code:
program TCMWebservice;

uses
  ActiveX,
  System.Win.ComObj,
  Vcl.SvcMgr,
  SysUtils,
  StrUtils,
  Web.WebReq,
  IdHTTPWebBrokerBridge,
  srvMain in 'srvMain.pas' {GFSRestWebservice: TService},
  serviceConsts in 'serviceConsts.pas',
  ModDb in 'modules\ModDb.pas' {DataModule1: TDataModule},
  ModWebModule in 'modules\ModWebModule.pas' {WebModuleMain: TWebModule},
  ModSessionHandler in 'modules\ModSessionHandler.pas' {SessionHandler: TDataModule};

{$R *.RES}
var
  sName    : String;
  DBConInit : TDataModule1;

begin
  if not Application.DelayInitialize or Application.Installing then
    Application.Initialize;


  if WebRequestHandler <> nil then
  begin
    WebRequestHandler.WebModuleClass := WebModuleClass;
  end;
  Application.CreateForm(TTCMRestWebservice, TCMRestWebservice);
  Application.CreateForm(TSessionHandler, SessionHandler);
  try

    sName := ExtractFileName (ParamStr (0));
    sName := AnsiReplaceText (sName, ExtractFileExt (sName), '');

    TCMRestWebservice.Name       := sName;
    TCMRestWebservice.DisplayName := sName;

    sName := EmptyStr;

    Application.Run;
  except
  on E: Exception do

  end;
end.
Markus
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#10

AW: WebModule & ADOConnection in Service -> Speicherübrelauf

  Alt 16. Jan 2017, 13:44
Momentan hab' ich da keine Idee mehr, nur was zum Lesen: MSDN - CoInitialize function

When do I need to call CoInitialize() in this scenario?

Multithreaded Delphi Database Queries

Ob dort eine Lösung zu finden ist, vermag ich nicht zu sagen.

Edit:

Was mir da gerade noch so einfällt:

Statt ADO die ZeoLib nutzen. Sie kann auch mit ADO umgehen und damit auch über ODBC auf was auch immer zugreifen.

Geändert von nahpets (16. Jan 2017 um 14:07 Uhr) Grund: Text ergänzt
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      

 

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 19:14 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz