IT技术博客大学习 共学习 共进步
全部 移动开发 后端 数据库 AI 算法 安全 DevOps 前端 设计 开发者

网络方面一些经验

我思故我在 2011-01-12 23:18:19 累计浏览 4,096 次
本机暂存

    网络协议里关于流量控制、提高交互效率、提高稳定性的部分,个人认为是最难的部分,以致于在LINUX内核里相关的实现都有BUG。前些年在追查一些网络故障的时候,看了些文档,一直想写些总结文章,但是这方面的内容实在太零散了,相关的RFC文档都好几个,把这些内容都说一遍,基本就把TCP/IP协议说了一遍。就只能挑几个CASE说了

    1、连接耗尽,这一般是短连接造成的。解决方案是,用长连接。这个方法看起来简单,其实很难,长连接会碰到更多各种各样的委琐事,不考虑性能的情况,还是用短连接简单。不过一般的公司都会有抽象出来的连接池一类,可以解决这个问题。用起来简单,只是追查问题的时候不知道从哪入手。

    当然也有委琐一点的解决方案,比如ulimit,或者,如果是A向B请求数据,B返回数据,然后双方关连接的交互模式,要求B先关连接,至于为什么这样做,我也解决不清楚,可以查一下timewait的说明。

    2、交互延迟,或者丢包(这可能也是延迟造成的,超时后不等待了,在上层看来就是丢包)。这个问题非常复杂,有各种杂七杂八的可能。常见于长连接。首先一种可能是,有的算法是,要求一次凑够多少数据才发送。这主要是因为,每发送一个包都要附加很多描述,比如包的长度、IP等,如果一次只发一点数据会很浪费,所以会凑。在强调时效性的场合,最简单解决的方法是直接关闭这一算法,但是LINUX的实现有BUG,要小心。还有一种可能是,发送方为了避免重发太多包,会在等到接收方返回ACK之后,再发送新的包,如果等不到,则重发旧的包,而接收方为了节省ACK的开销,会把几个ACK凑在一起,或者附在别的数据包上一起发回去,这样可能会导致ACK迟迟不来,然后发送方一直在等。最简单的做法是,在应用层把一次交互需要的包合成一个大包,一次发送,但是如果包实在太大了,还是会分多次发送的,不能治本。把多个小包凑成一个大包,表面上看是一件很简单的事情,实践中却是很艰难。这种模块间的交互,很可能是不同的项目组在做,别人才不管这边的延迟、KPI啥的,这件事情做了大半年才做完。还有别的可能,一时没想起来

    3、带宽过小,带宽过小的原因非常多,这里就不一一讨论了。首先一点是,在系统出现问题的时候,要识别出是带宽的问题,而不是模块本身性能问题。一般的做法是,执行一下scp之类的操作看一下带宽能到多少。在专用光纤的情况下,如果带宽还是很小,很可能是因为延迟太大了。TCP会要求,在接收到ACK之前,至多发K个包,在延迟非常大的情况下,发一次ACK就要20MS(可以PING一下),这时候一秒至多就能发50K个包了,所以解决的方案是把K增大。K也不能无限增大,因为K太大,一旦出错,需要重传的包会很多,考虑网络情况,适当取舍。很多时候光增大K是不够的,一般的模块,会有一个机制,需要知道下游的模块是否在处理自己的数据(有可能机器收到了,但是处理模块挂了),这需要下游模块显式地发送一个应答,这也会导致延迟,还需要相应地调整响应机制。所以用通用的消息队列传输数据会比较好,不需要每个模块都考虑这个问题。

    4、交互双方对交互成功、失败的结果不一致。比如A向B发数据,A显示写成功,而B显示读失败。这一般是因为写操作,只是把数据从模块的BUFFER写到操作系统的BUFFER

同分类推荐文章

  1. 等了十年的 Go 链式管道,终于来了:seq 让你像写 Scala 一样写 Go (2026-06-25 18:38:18)
  2. Go 实验特性详解 (2026-06-21 10:05:27)
  3. amd64 微架构级别对 Go 程序性能提升多少? (2026-06-21 09:38:49)

查看更多 后端 文章 →

建议继续学习

  1. Linux如何统计进程的CPU利用率 (累计阅读 16,308)
  2. 我的 RHCA 之路 (累计阅读 14,014)
  3. Linux内存点滴 用户进程内存空间 (累计阅读 13,232)
  4. 给程序员新手的一些建议 (累计阅读 13,090)
  5. Linux 性能监控、测试、优化工具 (累计阅读 13,013)
  6. 关于linux内存free的一些事情 (累计阅读 12,870)
  7. ps - 按进程消耗内存多少排序 (累计阅读 12,691)
  8. Google怎么用linux (累计阅读 12,583)
  9. Linux Used内存到底哪里去了? (累计阅读 11,868)
  10. find命令的一点注意事项 (累计阅读 11,867)