Delphi 7 Indy 9多线程HTTP服务器

时间:2014-06-29 13:28:47

标签: web-services delphi webserver indy httpserver

我需要编写一个多线程HTTP服务器。我知道Indy通过IdThreadMgrPool处理线程。

我的要求很简单:让服务器接受多个并发客户端(Web浏览器POST请求),运行调用Delphi DLL的有限数量的线程(可能与连接线程分开),并返回结果。

非阻塞将是最终的(如node.js)。

此主题有几个SO帖子。我在这里(或通过谷歌)找到的是如何使用IdThreadMgrPool的示例。我看到帖子说它必须使用,但没有示例如何。 Indy的网站上也没有例子。

有人能给我一个例子吗?或者是否有适用于此的FOS框架?

一个想法是让Indy正常生成多个线程,然后让这些线程访问运行DLL的受控线程池。如果这是合理的,那么我只需要知道"正常"案例用法示例。

4 个答案:

答案 0 :(得分:4)

要使用TIdThreadMgrPool,您至少需要创建一个实例,将其分配给TIdHTTPServer.ThreadMgr属性,并设置其PoolSize属性。所有这些都可以在设计时完成。

请记住,PoolSize不限制服务器上的连接数。为此,服务器有自己的MaxConnections属性。例如,您可以拥有10个PoolSize并同时连接15个客户端,从而运行15个线程。当它们断开连接时,10个线程将被放回池中,5个线程将​​被终止。

要自定义池线程,您可以从TIdPeerThread派生一个新类,可选地覆盖其虚拟BeforeExecute()AfterExecute()方法以执行每个线程初始化清理,然后分配在激活服务器之前,该类在运行时的服务器(而不是ThreadMgr)ThreadClass属性。在服务器事件处理程序中,您可以将提供的TIdPeerThread对象强制转换为自定义类,并根据需要使用它。

您可以向自定义线程类添加方法,并让它们在内部访问DLL,并根据需要进行限制。最简单的节流是使用单个共享信号量来控制一次可以进入信号量的线程数。在这方面,即使15个线程正在运行,您也可以一次限制为2个线程。

既然你说你想“在一个线程中运行DLL”,那么信号量可能就不够了。在这种情况下,我建议使用I/O Completion Port代替。您可以让自定义线程类使用PostQueuedCompletionStatus()向IOCP发送请求,并等待响应返回。限制是通过为IOCP服务而创建的线程数来完成的,例如每个CPU核心一个线程。每个IOCP线程都会在循环中使用GetQueuedCompletionStatus()来接收发布的请求。

Indy不是异步的,因此您无法向IOCP发送请求,并在准备好后立即将响应发送回客户端。服务器使用管理客户端连接的相同线程将响应发送回客户端。因此,客户端线程必须向IOCP发送请求并等待其响应,然后将该响应发送到客户端。您可以定义包含TEvent的记录,调用DLL所需的输入值以及DLL响应的输出值。然后创建该记录的实例,将指向它的指针发送到IOCP,并等待TEvent发出信号。当IOCP线程接收到记录指针时,它可以根据需要调用DLL,用响应填充记录,然后发出记录的TEvent信号。然后,取消阻塞等待的客户端线程,并根据需要将记录的响应数据发送到客户端。

答案 1 :(得分:2)

Indy服务器无法很好地扩展。

考虑使用http.sys内核模式服务器,基于iocp。

我们的开源SynCrtSock单元具有高性能的http服务器,从Delphi 5到XE6都可以完美运行。

例如参见this sample code

答案 2 :(得分:1)

如果您有可用的Windows服务器,我建议您使用Delphi 7编写ISAPI DLL并将其部署在IIS上,这将解决您的所有服务器端问题,特别是如果您使用的是带有IIS 7.5(或更高版本)的Server 2008 R2。您的客户端可以使用Indy连接到IIS,Indy客户端与Delphi ISAPI的请求/响应模型相结合,支持多种功能,可以轻松地将数据从客户端传递到服务器端请求处理程序并返回到您的客户。 不需要ASP.NET - 所有本机Delphi和" classic" ISAPI应用程序模型。

Delphi 7将生成ISAPI应用程序代码 - 当IIS将它们发送到您的DLL时,您将获得一个动作编辑器来处理请求,这由您的客户端发送的URL决定。您可以持久保存会话信息,创建全局缓存,并且您基本上可以在ISAPI DLL的上下文中使用VCL的所有非可视方面。

IIS处理线程 - 可能会处理比您需要的更多的并发连接 - 并且还使您能够确定一次可以加载DLL的实例数,以及许多其他选项,例如回收,各种形式的身份验证和安全级别。您可以使用IIS的应用程序池功能进行扩展等。

我使用这种架构开发了几个大型企业级解决方案(嵌入在Delphi exe中的Indy客户端)。它是稳定的,相对无痛的#34;一旦了解了Delphi的ISAPI应用程序模型的基础知识和IIS部署的bugaboos。

如果您有此选项,为什么要重新发明轮子?

答案 3 :(得分:1)

在此处查看示例: http://sourceforge.net/p/xxm/code/HEAD/tree/trunk/Delphi/http/

线程池逻辑在这里: http://sourceforge.net/p/xxm/code/HEAD/tree/trunk/Delphi/common/xxmThreadPool.pas

Xxm实际上提供了一个可以编码的接口,因此结果可以通过IIS,Apache或具有多线程的 plain HTTP服务器移植。还有一个http.sys版本和一个在本地运行到Internet Explorer的连接器(非常适合调试)。这些中的每一个都有自动更新'版本,将热交换项目DLL并将其用于任何新请求(非常适合实时服务器)。