Chinaunix首页 | 论坛 | 博客
  • 博客访问: 180358
  • 博文数量: 28
  • 博客积分: 30
  • 博客等级: 民兵
  • 技术积分: 954
  • 用 户 组: 普通用户
  • 注册时间: 2012-02-21 10:28
个人简介

站在巨人的肩膀是骗人的

文章分类

全部博文(28)

文章存档

2013年(28)

分类: C/C++

2013-04-06 09:27:27

在设计网络服务,我们一般会想用同步套接字还是异步套接字,用内核通知还是轮询但都少不了主动请求内核Recv数据的过程。
虽然这个Recv可以是同步(常规的recv,recvfrom)的也可以是异步(在windows上你可以使用WSARecv),但是都需要指定一块连续的BUFF空间。

在windows上使用异步socket,以及iocp的流程大体是这样:执行WSARecv(buff, size)=>从iocp得到完成通知,内核的数据已经拷贝到buff里,如果产生逻辑分组,拼接物理分成一个连续的缓冲=>执行WSARecv(buff, size)这样循环下去。
在linux上使用同步socket,以及epoll的流程大体是这样:从epoll得到可读通知,执行recv(buff, size),阻塞等待recv返回,如果产生逻辑分组,拼接物理分组成一个连续的缓冲=>执行recv(buff, size)...这样循环下去。

从上面流程可以看出,对于一个socket来说,当前只会有一个recv行为,需要等到下个当前的recv返回才会请求recv,所以这个时候很容易想到per-socket-data,我们为每个socket对应一个和socket生存期一致的recv_buffer就行了。
这个recvbuffer大小多少是可调整的,根据业务需求可以是8k,10k等。

数据recv成功后需要拼接成连续的,用以产生逻辑分组,这一步是必须的。也就是说,到目前为止,数据经历了4次拷贝。第一次,网卡数据到达,产生硬中断,使用DMA将网卡数据拷贝到内核空间。第二次是软中断,处理ip,tcp协议过程的一次拷贝。
第三次是内核空间交换到用户空间的拷贝(也就是recv)。第四次是产生拼接逻辑分组的拷贝。

从内核空间交换到用户空间,我们没办法控制,所以前面的3次必不可少。
我认为第四次也不可少,在做rpc时,数据必须连续,我们才能处理crypto,compress等。

第四次的目标缓冲如何设计?
我们也想到per-socket-data,为每个socket对应一个和socket生存期一致的buffer,用这个buffer来产生连续的逻辑分组。那么这个buffer应该多大好呢?如果我业务层面有一个分组超过10M,是不是我per-socket-data要增加10M,如果服务基数是10K,
那么就要增加10M * 10k的内存,是不是太大了点?如何才能接收任意大小而且最少使用内存的,不自然让我们想到,是否所有socket可以共用缓冲。而且顺便把第三次的目标缓冲也放在里面,这就是云风说的那个ring buffer。


阅读(7226) | 评论(3) | 转发(1) |
给主人留下些什么吧!~~

moon_rock2013-04-11 10:10:36

sxcong:比较好的做法是socket收到数据,提交给业务,缓冲开在业务层。这样不影响IO。毕竟现在处理速度远大于网速,能不影响socket就尽量不影响。
是否ring buffer应该是业务层上要考虑的,以网络视频为例,收到数据后能否解码,和socket一点关系没有,把数据向解码器一交,回头继续收下一帧。所以,“所有socket可以共用缓冲”这个设想没太大必要。每个socket内部缺省的缓冲已经够用了。回头再强调,其实,socket应该只管网络事件,其他的数据收发处理都应该由上一层去做,比如epoll的ET模式,你不处理数据,socket马上就会给你颜色看看,它才不管数据往哪放。

视频这类流媒体和rpc在缓冲上处理肯定不同

回复 | 举报

moon_rock2013-04-11 10:03:16

sxcong:比较好的做法是socket收到数据,提交给业务,缓冲开在业务层。这样不影响IO。毕竟现在处理速度远大于网速,能不影响socket就尽量不影响。
是否ring buffer应该是业务层上要考虑的,以网络视频为例,收到数据后能否解码,和socket一点关系没有,把数据向解码器一交,回头继续收下一帧。所以,“所有socket可以共用缓冲”这个设想没太大必要。每个socket内部缺省的缓冲已经够用了。回头再强调,其实,socket应该只管网络事件,其他的数据收发处理都应该由上一层去做,比如epoll的ET模式,你不处理数据,socket马上就会给你颜色看看,它才不管数据往哪放。

可能我没写明白,我说的socket缓冲是针对rpc的。

回复 | 举报

sxcong2013-04-11 09:42:36

比较好的做法是socket收到数据,提交给业务,缓冲开在业务层。这样不影响IO。毕竟现在处理速度远大于网速,能不影响socket就尽量不影响。
是否ring buffer应该是业务层上要考虑的,以网络视频为例,收到数据后能否解码,和socket一点关系没有,把数据向解码器一交,回头继续收下一帧。所以,“所有socket可以共用缓冲”这个设想没太大必要。每个socket内部缺省的缓冲已经够用了。回头再强调,其实,socket应该只管网络事件,其他的数据收发处理都应该由上一层去做,比如epoll的ET模式,你不处理数据,socket马上就会给你颜色看看,它才不管数据往哪放。