[fpc-pascal] How to use FCGI in threaded mode?

silvioprog silvioprog at gmail.com
Mon Feb 16 20:42:54 CET 2015

On Mon, Feb 16, 2015 at 7:23 AM, Michael Van Canneyt <michael at freepascal.org
> wrote:
> On Sun, 15 Feb 2015, silvioprog wrote:
>> On Sun, Feb 15, 2015 at 7:11 AM, Michael Van Canneyt <
>> michael at freepascal.org> wrote:
>> [...]
>>       Very nice.
>>       Some remarks:
>>       - KeepConnection logic already existed. It is part of the fastcgi
>> protocol.
>>         Normally, the apache server must send a keepconnection option as
>> part of the request.
>>         See the 'FKeepConnectionAfterRequest' variable in TFCGIrequest,
>> it is processed when
>>         the FCGI_BEGIN_REQUEST block comes in and is checked after each
>> request.
>>         The fact that you apparently needed to introduce special
>> processing means the proxy
>>         module does not correctly set this option. To test, you can check
>> the value of the flag
>>         in the request handler.
>>         I also suggest you look at the existing implementation of
>> KeepConnection and see
>>         where that needs to be changed, instead of introducing new
>> KeepConnection handling.
>> I saw, and it works fine in nginx, but ...
>>       - if you really need to introduce  an additional flag, please put
>> an extra flag in
>>         ProtocolOptions. Something like 'poDefaultKeepConnection'.
>>         Do not introduce new booleans 'options' when an option set
>> exists...
>> ... in Apache, using proxy mode, keepconn always returns true. =/ So we
>> need to add a 'poProxyKeepConnection' flag.
> Wait, I do not understand. If keepconn always returns true, then all
> should work as-is ? Why do you need the flag ?
> What happens if you set enablereuse=off in the apache config ?

I tried everything:

- KeepAlive Off;
- enablereuse=Off;
- SetEnv proxy-nokeepalive 0;
- disablereuse=On.

I tried environment variables too. I tried to add the FCGI_KEEP_CONN flag
to 0, and even so Apache return True. I happens only in Apache,  it seems
to be a bug, because I saw some people talking about this on StackOverflow.
The "enablereuse" feature was recently implemented, so it possibly has bugs.

On nginx I've just removed the keepalive  from upstram and all worked fine.

The poProxyKeepConnection flag will make the custfcgi hibrid, because the
programmer could choose between using the configuration via server or
application. So, add that. It worth. =)

      - Don't change the constructor signature, that is bad practice.
>>         A TComponent constructor must be Create(AOwner : TComponent);
>>         if you really want to change it, just create another one:
>>         Constructur CreateCustom(AOwner : TComponent; KeepConnection :
>> Boolean);
>>         For components, properties must always be settable after create,
>>         otherwise streaming does not work correctly.
>> Done. Please see the code in attached (some changes in mycustfcgi too).
> Thank you.
>> After your tips, now I'm able to implement the changes in original
>> custfcgi and send a patch. One more question before continuing: after
>> implementing the pool, we will still need RequestsArray?
> Normally yes, even more so than in the current implementation. IMHO you
> will maybe need 2 arrays: Incoming (request), outgoing(response).


But I don't know it we need two arrays, I think that a hash list will suit
well, I'll explain it below ...

> - New Request comes in. - No thread to handle request is available in pool.
> - Request is accepted and put in incoming requestsarray.
> - Check outgoing response array, send back any responses.
> - When Thread finishes a request, puts it in outgoing responses array.
> Details will depend heavily on the way the pool is handled.

... I don't know if you tested the code that I sent you, but I've already
done it, and in an unique array. =) The implemented structure works this

- the main acceptconn waits the first request;
- after receiving the first request, the execution comes from the main
acceptconn, creating a new thread, that has an own acceptconn;
- the first open thread keep waiting for new requests
in its own acceptconn, keeping the main acceptconn in 'stand-by'.

If an user make two or more later requests, it will call the acceptconn
from the thread, and the main acceptconn will go on in stand-by. If a
thread get in a long process (e.g: that 10 seconds loop), the main
acceptconn it will call, that leaving from the stand-by status, creating a
new thread, putting this new processing on it.

In short, if a request is short, only one thread is created and one
acceptconn is used; if a new request takes some time to be processed, the
application opens a new thread to process the other requests.

Another thing: IMHO, it is interesting to use hash lists instead of commom
arrays. A hash list has a internal generic array, that implements the type
of the array item according to the declared specialization. In some cases,
we get more than 700 % of performance using hash lists instead of commons
arrays. It happens due to the hash list uses a different logic to iterate
items. Please, test this small comparation[1] (Commom: 00:00:07.554 vs
Hash: 00:00:00.109) in your PC (considering that we will use only the
'add', 'get' and 'delete' methods of the list), realising the big advantage
in use hash list (you can compare them even with common arrays). We could
make a TFCGIThreadedList, using a critical section to turn it thread-safe
(on the comparition I showed you how to do it).

It is interesting to enjoy this big performance of the hash list, so, in
HTTP 1.1, the requests occur asynchronously: when a user open any page from
a site, the download of files JS, CSS, HTML, PNG etc. they are
done simultaneously (my calc of 150,000 iterations was supposing that
10,000 users was accessing a social network, and each user downloading in
average 15 page files - CSS, JS, HTML and ajax GETs -, simultaneously).

[1] http://pastebin.com/ZM1DSLkG

Silvio Cl├ęcio
My public projects - github.com/silvioprog
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20150216/d0a4aedc/attachment.html>

More information about the fpc-pascal mailing list