<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">Please excuse me for not answering you before ...<br></div><div class="gmail_quote"><br></div><div class="gmail_quote">On Wed, Feb 11, 2015 at 4:59 AM, Michael Van Canneyt <span dir="ltr"><<a href="mailto:michael@freepascal.org" target="_blank">michael@freepascal.org</a>></span> wrote:<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span>
On Tue, 10 Feb 2015, silvioprog wrote:<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<br>
Buddy, I finally could make a draft of a FastCGI application running in multi-thread in proxy mode. =)<br>
</blockquote>
<br></span>
Congratulations !!</blockquote><div><br></div><div>Thank you! =)</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
It worked on:<br>
<br>
. Windows 7 - 64 bits;<br>
. nginx 1.7.9 com o módulo FastCGI distribuído nele;<br>
. Apache 24 (httpd-2.4.12-win64-VC11.zip), que já vem com o módulo FastCGI com suporte ao modo proxy;<br>
. FPC do trunk.<br>
<br>
And the steps to test it were:<br>
<br>
. download and unzip the attached package, after unpacking it, enter the nginx directory and apply its settings in your copy (ainda<br>
não testei no Linux, mas farei isso em breve I haven't tested it on Linux yet, but I'll do it soon);<br>
. open and run the project1.lpr project;<br>
. open a tab in the browser and access <a href="http://localhost:81/test?op=loop" target="_blank">http://localhost:81/<u></u>test?op=loop</a>, it is supposed to be frozen for 10 seconds;<br>
. open another tab in the browser and access <a href="http://localhost:81/test" target="_blank">http://localhost:81/<u></u>test</a>, it is supposed to show the current time, even with the first<br>
tab frozen, this shows that the application is working in multi-thread.<br>
</blockquote>
<br></span>
I will test this ASAP :)</blockquote><div><br></div><div>Good! =)</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
Follow attached a unit called mycustfcgi.pp, that is a copy of the trunk custfcgi.pp. I've not created a patch because I believe that<br>
it will enter a new class in this unit, probably called TFCGIThread, and it won't be necessary a programmer treat the AcceptConnection<br>
method externally and not create extra classes, like "TFastCGIThread" and "TFastCGIRouter" as in the example.<br>
</blockquote>
<br></span>
Yes, Ideally, it should be simply a property 'Threaded' in TFastCGIApplication.<br>
<br>
But, I have looked at the code, and I have several remarks/questions: you create threads as requests come in.<br>
<br>
This can easily explode. I would prefer an approach where there is a thread pool,<br>
with a size that can be set at startup, or at least a maximum number of threads to start.<br>
<br>
Do you think you can change the design so it uses a thread pool ?<br></blockquote><div><br></div><div>Yes I can, I had thought about a list of threads, but I did without it just to check how a multi-threaded application behaves in an HTTP server in proxy mode. =)<br></div><div><br></div><div>In the end implementation, we will have a thread-safe list, so we'll be able to add a property to limit the maximum number of threads allowed in the pool. And each item in the pool may also have an extra property (property Date: Pointer), allowing the programmer to use it to save some optional information (I plan to use it to save the each user session in the memory).</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
Then: you create an instance of the FastCGIHandler for the request, but you do not copy the handler's properties (event handlers and so on). How is then for example the eventhandler OnIdle called ?<br></blockquote><div><br></div><div>That's it. That code was just an example to see the "hello" on the screen, but the end implementation will have a clone of the request/response in each thread. =)<br></div><div><br></div><div>I have a question, what is the OnIdle used for? If I got it, it waits for more requests on the same thread. Is it right?<br></div><div><br></div><div>Watching the following code:<br></div><div><br></div><div><div>      If (poUseSelect in ProtocolOptions) then</div><div>        begin</div><div>        While Not DataAvailable do</div><div>          If (OnIdle<>Nil) then</div><div>            OnIdle(Self);</div><div>        end;</div></div><div>...</div><div>    until Result or (FHandle=THandle(-1));<br></div><div><br></div><div>It seems that it is triggered when there is no data in the socket. If I'm right about this, I can create a OnIdle for each socket.</div><div><br></div><div>As we are going to change this part of the code, we could create the DoReadingData and DoWrittingData methods, they could be used to show a progress of sent and received data to the application. But it can be implemented later.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
Maybe it is better to refactor the code so there is a separate 'FastCGIIOHandler' object or something like it.<br></blockquote><div><br></div><div>So, If the OnIdle is used to wait for more requests on the same thread, we could create this class above, and it can be an attribute of the thread, handled in a loop in the thread, and to catch the OnIdle of triggerred in each thread, we could create a kind of "listener", that is just another property in the thread-safe list itself, avoiding thread deadlock.<br></div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
Another question.<br>
As I see it, you create a thread per accepted connection. Each connection can handle multiple requests. All requests on a connection are handled within the same thread.<br></blockquote><div><br></div><div>Yes. I have a micro chat application that I created using my own protocol, and there I use a thread per request. But it is a structure that I created by myself, so it could be different from the structure and proposal of FastCGI. I came up with a question: how can I configure the FastCGI to accept more than one request per connection? Is it possible in proxy mode?! I saw the RequestsArray property and it drove me to think that you receive more than one request per connection.</div><div><br></div><div>I need to understand this structure to implement a listener, where each thread will have its own events and they could be accessed asynchronously.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
What about an approach where there is a pool of threads that handles requests ?</blockquote><div><br></div><div>It will be a perfect approach!<br></div><div><br></div><div>I'll try to do it in the most performative and simple way as possible, then I'll send each change for you to evaluate, so when it becomes usable, we could apply it in the trunk. =)</div><div><br></div><div>I will also be very careful not to break the compatibility of custfcgi with legacy applications.<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
I believe that with some tips of you, I can make this implementation by myself and then send a patch.<br>
<br>
It would be great if this feature has already come in FPC 3.0, which is about to be released. =)<br>
</blockquote>
<br></span>
We will see, I think this is a big feature, and that is "bad" because big merges to fixes branch are not easily accepted.<br></blockquote><div><br></div><div>No problems buddy. =)<br></div><div><br></div><div>I'm planning to create an open source library (DLL/SO) to use the FPC FastCGI layer in other languages (at first in Delphi7 and XE7). I've already made a draft and it is working perfectly, but I want to make it multi-threaded, so I can use the FPC by branch fixes, applying my changes locally, and wait for them to be applied in the official repository.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Anyway: Great work !</blockquote></div><div class="gmail_extra"><br></div>Thank you. And I thank you for the great help you are providing me! =)</div><div class="gmail_extra"><br></div><div class="gmail_extra">Pretty soon we'll have a robust structure to use FastCGI in multi-thread mode ...<br></div><div class="gmail_extra"><br></div><div class="gmail_extra">-- <br></div><div class="gmail_extra"><div>Silvio Clécio<br>My public projects - <a href="http://github.com/silvioprog" target="_blank">github.com/silvioprog</a></div>
</div></div>