讨论:高性能的服务器程序设计方案

hxyman 2009-12-23 10:39:07
加精
这两天看了一些资料.说windows上用iocp处理大量连接时是最高效的.
我还没有用过iocp,就我现在了解的有这几个要注意的地方:
1.在io线程内不能有阻塞的操作,要尽可能地立即返回.
2.io线程数最好是等于cpu的个数.
3.具体的逻辑处理最好另开线程或线程池来处理.
就我的理解,如果是这样的话,就肯定需要一个数据队列.io线程收到数据就放到数据队列中,然后立即返回.逻辑处理的线程就从这个数据队列取出数据来处理.

不知道我上面说的是不是对的?或者说这样处理是不是最高效的?

还有,像这种多个线程操作同一个队列的情况一般是要加锁的.加锁就免不了性能下降了.
我现在想到一个不加锁的方法,请各位帮我看看可行不:
内存:分配一块全局的内存,分成一小块一小块,假设分成10块,每块500字节:[0,1,2,3,4,5,6,7,8,9]
线程:1个io线程(用iocp),N个数据处理线程.
io线程收到数据并拼包,放入到索引的内存块中,
然后把索引postthreadmessage给数据处理线程(轮流post给N个数据处理线程的每一个,保存每一个数据处理线程得到同样多的数据包),
同时索引号增1,
当索引值到达内存块数的一半时,比如这里是索引到达4时,给每一个数据处理线程post一个消息,数据处理线程收到这个消息后,会给io线程回传一个信号,比如setevent.
当io线程的索引用到内存块的末尾9时,就检查是否还有数据处理线程正在处理0-4索引的内存块(前面到4时post的那个消息就是起这个作用),如果没有数据处理线程占用,就把索引号重新从0开始.如果还有数据处理线程占用,就一直等待.同理在索引值是9的时候也要post一个消息然后在4的时候检查...
这样就想当于两个缓冲区切换.除了在切换的时候要等待一下,其余的时候都不用考虑.而且如果块数足够多,切换时一般是不需要等待延时的.

还有个疑问,就是io线程拼包所用的时间可不可以接受?会不会太费时?如果把拼包的工作交给其它线程做好像也不好,因为像http这类服务,要根据socket区分每一个用户.

欢迎大家讨论一下^..^
...全文
2791 71 打赏 收藏 转发到动态 举报
写回复
用AI写文章
71 条回复
切换为时间正序
请发表友善的回复…
发表回复
liaomingdong 2010-03-06
  • 打赏
  • 举报
回复
正在研究这些服务器端,发现实在不容易哦.
Allen_晓明 2009-12-30
  • 打赏
  • 举报
回复
[Quote=引用 47 楼 hxyman 的回复:]
引用 2 楼 vieri_ch 的回复:
嗯工作线程,负责处理完成通知包,尽可能的把数据缓存起来。当然在这里就要分客户端socket来缓存。这就要求每个WSARecv,不要完全按照应用协议分包接收,应该是按照应用协议分包的10倍来投递请求。多少倍,看你单个协议包的大小来决定。因为网络IO本身就是相对内存IO是低速的,所以在这里拼包,得不偿失。
另外一个线程负责把缓存的包数据,处理拼包逻辑。因为此时是内存IO,肯定比工作线程去处理要快

嗯,受教了.


引用 28 楼 joey_ 的回复:
引用 17 楼 axman 的回复:
连接的客户端中有5%或10%以上的用户网络连接很差,比如每秒只能传50个字节。或者一个恶意客户端,比如我,故意和你建立一个连接,在一定范围内比如每3秒发一个节字。但我也不断线。

也发表下自己的看法.
首先,这种状态这种状态比较难以维持你不断线;

其次,可以通过服务器逻辑做简单的历史状态判断,如果客户端的网络状态很差,就暂时中断该客户端的网络请求,直到检测到该客户端达到某一标准后,方开放对该客户端的网络服务.

经过增加这样的服务器逻辑处理后,服务器的网络效率就会保持在一个较高的水平,目前我们的mmorpg网游就是这样做的,实际的使用效果比较良好.

确实要考虑这种问题,现在互联网环境很恶劣.

引用 22 楼 wenxy1 的回复:
微软有IPCP(完成端口),Linux下有epoll模型。
参考:http://blog.csdn.net/flyingtimeice/archive/2009/03/13/3987297.aspx

谢谢,这个讲的很形象.我下了几个iocp的例子,觉得 大宝那个iocp 的例子不错, <Windows网络与通信程序设计>讲iocp时好像直接用了大宝的这个例子.(也不知道谁是原创-..-)

灰常感谢参与讨论的朋友.灰常感谢版主置顶.

还有个疑问,同时在线的socket比较多时,一般是用什么结构来存比较好,hash? 单链表?
暂时先不结贴,大家继续讨论,谢谢:)
[/Quote]

哈哈,CSDN还是有人的呵。一直在做局域网的分布式,还真没有考虑过恶意,极端情况哪。楼上几位说的不错。
如果极度考虑性能,建议不要采用一个线程收数据,缓存,另外几个线程处理的方式。 收数据,拼包,处理都在一个线程处理,可避免一次线程切换,亦不用队列了。“在io线程内不能有阻塞的操作,要尽可能地立即返回.”只是个一般的表述,并不是说io线程除了收数据其他的就什么都不能干了。即使你收数据的速度超级快,超过了你系统的处理,也是没有意义的。
如果跨平台,ACE值得考虑。
rightorwrong 2009-12-28
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 vieri_ch 的回复:]
嗯工作线程,负责处理完成通知包,尽可能的把数据缓存起来。当然在这里就要分客户端socket来缓存。这就要求每个WSARecv,不要完全按照应用协议分包接收,应该是按照应用协议分包的10倍来投递请求。多少倍,看你单个协议包的大小来决定。因为网络IO本身就是相对内存IO是低速的,所以在这里拼包,得不偿失。


另外一个线程负责把缓存的包数据,处理拼包逻辑。因为此时是内存IO,肯定比工作线程去处理要快
[/Quote]

您说的不要完全按照应用协议分包接收,应该是按照应用协议分包的10倍来投递请求是什么意思?

是不要按照定义的命令格式来接收包,是这个意思么?
应用协议分包的10倍来投递请求,不理解,请详细说明下。
内存IO的memcpy操作会影响性能么

请您说明下。谢谢
VCkid 2009-12-27
  • 打赏
  • 举报
回复
学习
Caijincheng 2009-12-27
  • 打赏
  • 举报
回复
很好啊
ddnetplay 2009-12-27
  • 打赏
  • 举报
回复
学习.Net需要了解的事情
small_warm 2009-12-27
  • 打赏
  • 举报
回复
good
ciahi 2009-12-27
  • 打赏
  • 举报
回复
Mark!
butong350 2009-12-26
  • 打赏
  • 举报
回复
进来看看!!
wucap 2009-12-26
  • 打赏
  • 举报
回复
写得不错
RIYAO1314 2009-12-26
  • 打赏
  • 举报
回复
干什么用的,可以提高网速吗?····(菜鸟
kongyi111 2009-12-26
  • 打赏
  • 举报
回复
ding
  • 打赏
  • 举报
回复
你的总结大概没有错 但是主还是要看你的软件的结构 和 你需要的功能
ly72188 2009-12-26
  • 打赏
  • 举报
回复
进来看看!!
不动如岳 2009-12-26
  • 打赏
  • 举报
回复
没有用过iocp
執迷王二 2009-12-26
  • 打赏
  • 举报
回复
过来看看 嘿嘿
plee1037 2009-12-25
  • 打赏
  • 举报
回复
mark 2 times
plee1037 2009-12-25
  • 打赏
  • 举报
回复
mark
cqsfd 2009-12-25
  • 打赏
  • 举报
回复
进来mark
hxyman 2009-12-25
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 vieri_ch 的回复:]
嗯工作线程,负责处理完成通知包,尽可能的把数据缓存起来。当然在这里就要分客户端socket来缓存。这就要求每个WSARecv,不要完全按照应用协议分包接收,应该是按照应用协议分包的10倍来投递请求。多少倍,看你单个协议包的大小来决定。因为网络IO本身就是相对内存IO是低速的,所以在这里拼包,得不偿失。
另外一个线程负责把缓存的包数据,处理拼包逻辑。因为此时是内存IO,肯定比工作线程去处理要快
[/Quote]
嗯,受教了.


[Quote=引用 28 楼 joey_ 的回复:]
引用 17 楼 axman 的回复:
连接的客户端中有5%或10%以上的用户网络连接很差,比如每秒只能传50个字节。或者一个恶意客户端,比如我,故意和你建立一个连接,在一定范围内比如每3秒发一个节字。但我也不断线。

也发表下自己的看法.
首先,这种状态这种状态比较难以维持你不断线;

其次,可以通过服务器逻辑做简单的历史状态判断,如果客户端的网络状态很差,就暂时中断该客户端的网络请求,直到检测到该客户端达到某一标准后,方开放对该客户端的网络服务.

经过增加这样的服务器逻辑处理后,服务器的网络效率就会保持在一个较高的水平,目前我们的mmorpg网游就是这样做的,实际的使用效果比较良好.
[/Quote]
确实要考虑这种问题,现在互联网环境很恶劣.

[Quote=引用 22 楼 wenxy1 的回复:]
微软有IPCP(完成端口),Linux下有epoll模型。
参考:http://blog.csdn.net/flyingtimeice/archive/2009/03/13/3987297.aspx
[/Quote]
谢谢,这个讲的很形象.我下了几个iocp的例子,觉得 大宝那个iocp 的例子不错,<Windows网络与通信程序设计>讲iocp时好像直接用了大宝的这个例子.(也不知道谁是原创-..-)

灰常感谢参与讨论的朋友.灰常感谢版主置顶.

还有个疑问,同时在线的socket比较多时,一般是用什么结构来存比较好,hash? 单链表?
暂时先不结贴,大家继续讨论,谢谢:)
加载更多回复(51)

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧