【发布时间】:2020-09-06 12:58:00
【问题描述】:
在我的项目中,我有一个运行 C# 应用程序的云托管虚拟机,它需要:
- 接受来自多个外部客户端的 TCP 连接(大约 500 个)
- 从连接的客户端异步接收数据(频率不高,大约每分钟 1 条消息)
- 对收到的数据做一些处理
- 将收到的数据转发给其他参与者
- 回复连接的客户端并可能进行一些异步发送(基于内部时间检查)
在我看来,这个设计很简单。我提供了一个接受传入 TCP 连接的侦听器,当建立新连接时会产生一个新线程;该线程在循环中运行(执行从 2 到 5 的活动点)并检查关联的套接字活动(如果套接字已死,则线程退出循环并最终终止;稍后将从套接字所属的外部客户端尝试新连接到)。
所以现在的问题是,对于有限数量的外部客户端(我会说 200/300),一切运行顺利,但随着数量的增长(或者当客户端以更高的频率发送数据时),通信变得非常缓慢和受阻.
我正在考虑一些更好的设计,例如:
- 使用任务而不是线程
- 使用线程池
- 将 1Thread1Socket 替换为 1Thread10Socket 之类的东西
甚至一些扩展策略:
- 在同一个应用程序中打开两个不同的 TCP 侦听器(不同的端口)(重新配置客户端,使其中一半针对每个侦听器)
- 在同一虚拟机上提供两个具有两个不同 TCP 侦听器(不同端口)的相同应用程序
- 设置两个不同的虚拟机,每个虚拟机上运行相同的应用程序(重新配置客户端,使其中一半针对每个虚拟机地址)
最后的问题是:当前的设计是糟糕还是幼稚?你觉得我处理沟通的方式有什么重大的关键吗?你有没有更强大和有效的选择(在上面提到的那些,或者任何其他的)?
谢谢
【问题讨论】:
-
已知每个连接的线程不能很好地扩展。
-
是的,完全反模式。并且完全忽略那里存在的批量 API - 回到文档。而且您的一些扩展策略(尤其是第一个)听起来完全像是不阅读文档(即选择仅选择有数据等待的套接字)。目前的设计很幼稚。还有这个 ftopic 的问题。
-
@TomTom 你能不能给我提供几个有用的链接来更好的模式?谢谢
-
当然。 docs.microsoft.com/en-us/dotnet - 我把它当作一个练习来了解框架以在 Socket 类上找到 Select 方法。
标签: c# multithreading tcp communication scalability