可伸缩的 Delphi TCP 服务器实现

9
有没有关于用作可扩展TCP服务器基础组件的建议?我目前有一个使用Indy实现的方案,可以处理100个相对活跃的连接或1,000个相对不活跃的连接,但每个连接模型只能限制可以处理的并发活动连接数量。假设我的目标是在良好的服务器上(8-16个核心),每个处理10条消息/秒的1,000个连接,或每个处理1条消息/秒的10,000个连接。这是现实的吗?我真的很想听听任何实际实现的经验,因为我发现理论上可能行得通的东西在实践中未必行得通,而我不想追逐一个行不通的解决方案。
编辑:IOCP可能很好,但我只想使用商业级别的类/组件,所以它们需要像Indy或IP*Works一样“专业”。此外,我无意“自己动手”,因为把它变成商业级别需要太多时间。最后,我正在寻找比我已经拥有的更大的改进。我确信我至少可以从我已经拥有的(基于Indy)中挤出20-50%以上的性能,但我永远无法处理10,000个并发客户端或每秒10,000条消息,无论我怎么努力。是否存在符合这些条件的东西是另一回事。
我已经决定接受关于IOCP类的答案,尽管我没有使用过它们,因为它们看起来是目前调查的最佳途径。

一些关于 Delphi 的 IOCP 解决方案的指针可以在这里找到:http://stackoverflow.com/questions/1072510/delphi-tclientsocket-replacement-using-winsock2-and-iocp 和 https://dev59.com/30zSa4cB1Zd3GeqPjhqK。 - mjn
请查看https://dev59.com/30zSa4cB1Zd3GeqPjhqK - 它将为您提供多个同时连接的最佳性能。 - Arnaud Bouchez
@mjn,Arnaud,那些关于IOCP的链接里面什么都没有,只是一个“我会尝试并看看”的说法。当然,甚至没有任何暗示表明在这个领域有商业级别的产品提供。 - Misha
我知道这是一个非常老的帖子,但我自己正在寻找可扩展的解决方案,我正在使用Indy TCP组件,但即使有400多个活动连接,它也会失败。 Misha,你最终得到了什么?我真的很感激你能给我一些提示或更多的提示 :) - Junaid Noor
6个回答

3

这里有一个项目,它是基于之前的iopcclasses项目的,位于http://voipobjects.com/

它声称可以处理数千个同时连接

IOCP引擎是一组用于快速创建高可扩展性和性能的TCP/UDP应用程序的类、组件和例程。使用IOCP类创建的应用程序可以处理数千个并发连接。该库使用Delphi编写-Delphi 7-2010受支持。库使用IO完成端口技术,这是Win32世界中用于创建高度可扩展和性能TCP/UDP应用程序的最强大技术。除旧版Win9x / WinME版本外,所有桌面Windows操作系统都支持此技术。此库根据MPL1.1许可证获得许可。还包括来自Jedi项目(Winsock2标头翻译)的一些文件。https://bitbucket.org/voipobjects/iocpengine

这看起来是最有前途的选择。目前处于活跃状态(相对较新的错误修复),并且有着重要的代码库。我一定会去看看它。 - Misha
嗯,唯一的真正竞争者已经消失了 - 很奇怪! - Misha

2
我最喜欢的Delphi网络层是 Francois Piette的ICS。它非常易于理解、可扩展性强、性能超高。它是免费和开源的。对于大多数人来说,它可能会扩展到1000个客户端,而无需额外的努力,并且不会像使用Indy时那样复杂,让我感到困扰。

将我的所有东西从Indy切换到ICS后,我获得了大约20%的可扩展性/性能提升。


我也会查看ICS。 - Misha
我不知道ICS使用I/O完成端口。你能确认一下吗?顺便说一句,Indy可以非阻塞地使用,因此通过相当大的工作量可以在线程之间共享连接。但是,我认为这可能是一个重要的工作。 - Misha
@Misha,我刚刚删除了我的评论。我不确定ICS是否被阻止了,相反地,我混淆了ICS和IOCP。 - Arnaud Bouchez
1
我也喜欢ICS。但要注意它使用Windows消息非常频繁,并且对处理这些消息所需的时间非常敏感。如果1000个并发连接进行大量I/O通信,ICS可能会失败。 - Cosmin Prund
1
@Cosmin,我想避免使用基于Windows消息的解决方案,因此ICS不适用。 - Misha

1
你应该看看RealThinClient SDK http://www.realthinclient.com/about.htm 这是一个经过验证的解决方案,拥有良好的支持。主页上提供了不同服务器解决方案的测试结果。

我确实需要基于TCP的解决方案的灵活性(我做的很多事情都是从服务器向客户端推送未经请求的通知),而不是基于HTTP的解决方案,尽管这仍然值得研究。 - Misha

1

真正决定的因素是您计划在每个交易中做什么。

我使用Indy与网络负载平衡的Windows服务器。其中一个Delphi应用程序由3台物理服务器提供服务,监听一个公共IP地址,自昨天以来我们已经收到了数百万个请求,没有错误。夜间负载相当空闲,因此实际请求在白天期间大约为每秒/服务器350个,并且有足够的增长空间。

如果每个事务不需要太多CPU /内存,您可能可以使用Indy在一个框中完成它。这完全取决于负载...因为您可能无法每秒写入1000个不同的文件。

还有其他要担心的问题-例如操作系统是否支持这种活动量。您可能需要调整一些注册表设置。(请参见此stackoverflow question

IOCP是超高容量服务器的选择。我很长时间以来一直使用Indy进行实现/调试,因为它易于使用。我有自己的IOCP实现,几年前就编写了,但从未在生产中推出,因为我们根本不需要。

我的简单建议是 - 我强烈建议在Indy中推出它,使用NLB作为负载的支撑,并且如果您仍然想要最大限度地提高速度,那么编写自己的IOCP实现,以便您可以根据自己的特定要求进行调整。请注意,这是基于不知道实际实现要求的情况下提出的建议。

我过去3年已经部署了基于Indy的生产解决方案。我喜欢它,到目前为止它一直在为我工作,处理100-200个并发客户端的系统以及突发活动的负载都可以应对。有很多地方我可以进行性能调整,但目前我面临的根本限制是高数量的活动连接会导致太多的上下文切换。我可能可以从单个良好的服务器获得500-1000个请求/秒,但超出这个范围后,每个连接一个线程的问题就会出现。请参见下面关于IOCP的评论。 - Misha
Indy对于100-200个并发客户端表现良好。但是对于1000个客户端来说,至少对我来说不行。 - Warren P
@Warren P,完全同意,因为1,000个客户端意味着1,000个服务器连接线程,而且如果它们都是活跃的,那么上下文切换的数量就很多。 - Misha
我的服务器有时会达到8-900个活动连接,但如果一直保持在1000个,则快速简单的解决方案是两台每台500个的服务器。您可以设置NLB集群,以便亲和力属于特定服务器(将客户端连接到同一服务器)。底线-如果您有1000个活动事务,则会影响你的是您正在尝试在同一台服务器上同时进行的这1000个事务的操作。 Delphi通常不能充分利用很多核心。 - Darian Miller
我已经处理了实际的数据处理 - 我有一个线程框架,可以让我充分利用所有可用的核心。如果处理是无状态的(有时可能),我可以通过更新配置文件并行多个数据处理线程。但是客户端连接限制了我的处理能力。 - Misha
显示剩余3条评论

0

我尝试了多种Delphi解决方案来进行网络编程,并发现许多(如果不是全部)解决方案都会增加复杂性和代码,从而影响性能或占用空间,有时甚至两者兼而有之。因此,我开始寻找对winsock API进行最轻量级封装的方法。然后我(重新)发现了Delphi自带的TTcpClient和TTcpServer组件。在阻塞模式下使用,并重写TCustomTcpServer的DoAccept方法,我至今获得了最好的结果。

如果您预计会有大量的传入连接和(小型)响应需要提供给(小型)请求,强烈建议实现I/O完成端口,因为这样可以更好地处理传入请求。


1
是的,我的解决方案比Indy增加了很多复杂性(大约10,000行代码),但它被很好地管理并且非常稳定。我同意I/O完成端口可能是正确的选择,但我想使用比自己构建更高级别的抽象层。 - Misha

0

我在过去的12年中一直在使用ICS。它是非阻塞的。我支持最多2000个并发连接,每个连接至少每秒获取5000字节,每200毫秒发送1000字节。从未遇到任何问题,并且应用程序的CPU使用率非常小。 论坛提供了良好的支持,但根本不需要。

谢卡尔


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接