请僵哥等高手解答IOCP优化难点?

wakawaka99 2011-10-29 01:24:29
小弟不才,请CSDN大牛解决IOCP优化问题:
proxy server构架:
a)转发服务端s1采用IOCPx3模式:针对客户端c的收发包,使用IOCP-1;针对其他服务端s2的收发包,使用IOCP-2;业务层逻辑包通过IOCP-3转发到1或者2;
b)网络层(IOCP-1/2)只负责收发包,收到包后投递到IOCP-3,然后视业务逻辑分别转发给IOCP-2或1,处理或再投递;
c)为防止大量非分页内存锁定:WSASend已做队列缓冲;WSARecv在连接进来后,投递0字节WSABUF。

问题来了:
问题一:在监听线程接收连接后,分配上下文并投递0字节缓冲区的WSARecv,已经实现高并发大吞吐量数据的接收没有问题,由于投递0字节WSARecv解锁,所以非分页内存有升也有降很正常。
但是在GCQS接收大量并发数据时,如果s1使用shutdown+closesocket主动断开某个连接字(比如恶意发包攻击等),GCQS有可能接收不到该IO正常返回(正常的话在该套接字上投递的0字节WSARecv会返回),因此此时无法正常回收context,在cmd里面netstat -ano -p tcp,确定该连接已经被关闭,只是GCQS无返回。

我现在是这样处理的:投递0字节WSARecv,如果该连接上有包发过来,那么GCQS正常返回,然后再投递一分页4096字节的缓冲区WSARecv,然后GCQS再次返回,这时ioSize已经包含实际数据长度了,我粘包处理完后,继续投递0字节WSARecv如此循环。

问题二:另外看网上有另外一种方法:投递0字节WSARecv,有包过来,GCQS会返回,然后通过循环recv接收,直到recv返回-1,WSAGetLastError==WSAEWOULDBLOCK

实际测试中发现,因为默认套接字是阻塞的,所以recv接收完数据后,会阻塞,并不会出现WSAEWOULDBLOCK的情况,所以无法正常跳出。是否需要在recv()之前将套接字先设置为异步的?等出现WSAEWOULDBLOCK跳出后,再设置成同步的?
...全文
205 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
smwhotjay 2011-11-03
  • 打赏
  • 举报
回复
iocp并没有用线程池. 只需要几个辅助线程而已.

teleinfor 2011-11-03
  • 打赏
  • 举报
回复
使用IOCP模型,在同一个机器上使用这么多IOCP模型,似乎必要性不大,你不要过分的夸大IOCP的功能。IOCP就是利用了线程池技术,外加队列机制与异步方式来优化性能。具体IOCP模型的性能取决于你硬件CPU的数量和CPU内核数量,你没有必要同时开启多个IOCP服务进程或者线程,一个IOCP模型足以实现多个IOCP的效果。如果开启太多反而不利于效果。

如果为了考虑任务的分布式处理,那么建议你的架构采用分布式设计,任务按照进程划分后部署到不同的SERVER上完成各自的任务,SERVER间采用IOCP模型进行数据传递,岂不是效果更好?

个人理解,供参考。
pker911 2011-11-02
  • 打赏
  • 举报
回复
怎么不见僵哥等大牛来回答啊?是不是小弟的问题根本不屑解答。。。
最好有高手帖下你们压力测试的条件及结果,看看你们的IOCP的IO流量满载能达到多少。
wakawaka99 2011-10-30
  • 打赏
  • 举报
回复
假设包是128字节固定大小,来算下服务器流量:
下载(收包):6W x 128/s ≈ 7.3M/s = 58.4M带宽
上传(发包):600W x 128/s ≈ 732M/s = 5856M带宽 = 5.7G带宽

应该没算错吧?
局域网单机测试都不可能完成。
不晓得所谓IOCP上W并发连接+收发包,是怎么个上W法?估计服务端都是放在TX之类的公司用刀片的,网卡也真NB。
wakawaka99 2011-10-30
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 allen_zhang 的回复:]

对于你的问题暂时无法解释
不过有一个地方可以讨论一下:
同一个服务开多个IOCP会不会导致其他问题?
个人感觉无论多少连接等一个IOCP就可以处理了吧,没必要多个IOCP
反正IOCP就是管理连接和负责收发数据的
至于连接和数据是谁,提交给上层业务逻辑层来处理就行了,不知道是不是多个IOCP导致你上面的问题
[/Quote]

建议你做个测试,并发1000个客户端线程,连接服务端后平均1ms发送一个包;服务端收到一个客户端包后,需要粘包处理后再群发给当前1000个客户端,这样服务端的IO收发大概是:
WSARecv:1000包/ms --> 6W/s
WSASend:1000 x 1000 包/ms --> 600W/s

当然用我说的WSASend发送队列的话,可以计算XX秒内同一个连接是否有多个包需要发送,这样可以合并发送,减少WSASend锁定非分页内存的次数。

其实我觉得网上很多人说:IOCP可以高达上W并发连接,如果只用一个IOCP收发,试想一下在这种毫秒级的压力测试下是多么不堪一击(简单的echo排除在外)

稍微动点脑经想一下,上W并发毫秒级的压力测试,就算做发送队列合并的话,光是发送就会消耗大量非分页内存池,还不算接收的,假设x86的OS能把256M的nopage pool都给你的服务端用的话。

我觉得太多人神话IOCP模型了,说白了只是一个简单的由系统帮你调度入队出队的IO Queue,真正运用起来稍微带点复杂一点逻辑的的服务端单机也就2000并发。
wakawaka99 2011-10-30
  • 打赏
  • 举报
回复
同一个server可以开多个IOCP,这个其实也是实际需要决定的,当然如果只用一个IOCP就能在压力测试下保证很高的IO吞吐量,那也没问题。
至少我使用IOCPx3可以保证网络层的IOCP有很高的并发吞吐,如果此时需要转发的数据还使用同一个IOCP的话,会产生延迟是肯定的,你可以把IOCP想像成一个管道队列,读/写都往同一个IOCP投递,IO肯定是越来越多的,那么需要再转发出去的包理论上会产生比较大的延迟,所以我才把转发功能丢给另一个IOCP去处理。

流程图就不画了,简化一下如下所示:

ClientN <-> IOCP-1 :负责N个客户端的收发,如果有转发给其他服务端的包,投递给IOCP-2
IOCP-2 <-> ServerN :负责N个服务端的收发,如果有转发给其他客户端的包,投递给IOCP-1

IOCP-3是我逻辑层其他转发需要的,可以不用考虑。

如果都客户端与其他服务端之间的转发使用相同的IOCP,那么一旦某一方并发流量瞬间很高的话,会影响另一方的收发,因此我采用多个IOCP模型+中间层的IOCP转发就避免了这个情况。
Allen_zhang 2011-10-29
  • 打赏
  • 举报
回复
对于你的问题暂时无法解释
不过有一个地方可以讨论一下:
同一个服务开多个IOCP会不会导致其他问题?
个人感觉无论多少连接等一个IOCP就可以处理了吧,没必要多个IOCP
反正IOCP就是管理连接和负责收发数据的
至于连接和数据是谁,提交给上层业务逻辑层来处理就行了,不知道是不是多个IOCP导致你上面的问题
gold_water 2011-10-29
  • 打赏
  • 举报
回复
路过,帮顶 望大牛解答...

18,356

社区成员

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

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