简体   繁体   中英

Delphi 7 Indy 9 multithreaded HTTP Server

I need to write a multithreaded HTTP server. I know Indy handles the threading via IdThreadMgrPool.

My requirements are straightforward: have a server that accepts multiple simultaneous clients (web browser POST requests), runs a limited number of threads that call a Delphi DLL (likely separate to the connection threads), and returns the results.

Non-blocking would be the ultimate (like node.js).

There are several SO posts on this topic. What I can't find here (or via Google) is an example of how to use IdThreadMgrPool. I see posts that say it must be used, but no example how. There is no example on Indy's website either.

Could someone point me to an example? Or is there a FOS framework that will work for this?

One idea is to have Indy spawn multiple threads as normal, then to have these threads access a controlled pool of threads that run the DLL. If this is plausible, then I just need to know the "normal" case usage example.

To use TIdThreadMgrPool , at a minimum all you have to do is create an instance of it, assign that to the TIdHTTPServer.ThreadMgr property, and set its PoolSize property. All of that can be done at design-time.

Keep in mind that the PoolSize does not limit the number of connections on the server. The server has its own MaxConnections property for that purpose. For example, you could have a PoolSize of 10 and have 15 clients connected simultaneously, and thus 15 threads running. When they disconnect, 10 threads will be put back in the pool and 5 threads will be terminated.

To customize the pool threads, you can derive a new class from TIdPeerThread , optionally override its virtual BeforeExecute() and AfterExecute() methods to perform per-thread initializations the cleanups, and then assign that class to the server's (not the ThreadMgr's) ThreadClass property at runtime before activating the server. Inside your server event handlers, you can then typecast the provided TIdPeerThread object to your custom class and use it as needed.

You can add methods to your custom thread class and have them internally access the DLL, throttling as needed. The simplest throttle would be to use a single shared semaphore to control the number of threads that can enter the semaphore at a time. In that regard, you can then limit to, say, 2 threads at a time even if 15 threads are running.

Since you say you want to "run the DLL in a thread", a semaphore will likely not be enough. In that case, I would recommend using an I/O Completion Port instead. You can have your custom thread class post a request to the IOCP using PostQueuedCompletionStatus() and wait for the response to come back. Throttling is accomplished by the number of threads you create to service the IOCP, such as one thread per CPU core. Each IOCP thread would use GetQueuedCompletionStatus() in a loop to receive posted requests.

Indy is not asynchronous, so you would not be able to post a request to the IOCP and let it send a response back to the client directly when ready. The server sends a response back to the client using the same thread that manages the client connection. So the client thread will have to post a request to the IOCP and wait for its response, then send that response to the client. You can define a record that contains a TEvent , input values needed for calling the DLL, and output values for the DLL's response. Then create an instance of that record, post a pointer to it to the IOCP, and wait for the TEvent to be signalled. When an IOCP thread receives the record pointer, it can call the DLL as needed, fill the record with the response, and then signal the record's TEvent . The waiting client thread will then be unblocked and can send the record's response data to the client as needed.

Indy server does not scale well.

Consider using http.sys kernel mode server, iocp based.

Our open source SynCrtSock unit feature a high performance http server, and works perfectly from Delphi 5 up to XE6.

See for instance this sample code .

If you have a Windows server available I would suggest writing an ISAPI DLL with Delphi 7 and deploying it on IIS, which will handle all your server side issues, particularly if you have Server 2008 R2 with IIS 7.5 (or better). Your client side can use Indy to connect to IIS, and the Indy client combined with Delphi ISAPI's request/response model support several features which make it easy to pass data from your client into your server side request handler and back to your client. No ASP.NET required - all native Delphi and the "classic" ISAPI application model.

Delphi 7 will generate the ISAPI application code - you get an action editor to handle requests when IIS sends them to your DLL, which is determined by the URL your client sends. You have the ability to persist session information, create global caches and you have essentially all the non-visual aspects of the VCL available within the context of your ISAPI DLL.

IIS handles the threading - will probably handle far more simultaneous connections than you need - and also gives you the ability to determine how many instances of your DLL can be loaded at once, as well as many other options, such as recycling, various forms of authentication and levels of security. You can use the application pooling abilities of IIS for scaling, etc.

I have developed several large scale enterprise level solutions using this architecture (Indy clients embedded in Delphi exe's). It is stable and relatively "painless" once you get down the basics of Delphi's ISAPI application model and the bugaboos of IIS deployment.

If you have this option available, why reinvent the wheel?

See an example here: http://sourceforge.net/p/xxm/code/HEAD/tree/trunk/Delphi/http/

The thread pool logic is here: http://sourceforge.net/p/xxm/code/HEAD/tree/trunk/Delphi/common/xxmThreadPool.pas

Xxm actually provides an interface you can code against so the result is portable over IIS, Apache or the plain HTTP server with multi-threading. There's also a http.sys version and a connector to run locally right into Internet Explorer (great for debugging). Each of these also have an 'auto-update' version, that will hot-swap the projects DLL and use it for any new requests (great for live servers).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM