队列的玩法

生活中什么时候会出现队列?

食堂赶上刚下课,每个窗口排一长溜等着打饭 or 当看到一处美景却不能丢下一切拍马前往,只好掏出笔记把它塞到心愿名单,想着总有一天老夫聊发少年狂,左牵黄、右擎苍……

生活的经验告诉我们,当生产-消费速度不匹配时,我们可以用队列的形式弥补速度上的不匹配。

再拿 nginx + php-fpm 的队列大小举栗子。

一次 TCP 请求,服务端发生了:

  1. 初始化,socket 绑定,进入 LISTEN 状态,系统调用 listen 需要传入参数 backlog,与系统配置参数相比后,最小者被设置为实际队列大小。
  2. 接收到 SYN 包后,并将 connection 入 SYN 队列(半连接队列),进入 SYN RECEIVED 状态,并发给客户端 SYN/ACK 包。
  3. 接收到 ACK 包后,**将 connection 从 SYN 队列中转移到 accept 队列等待应用调用系统调用 accept 来消费**,进入 ESTABLISHED 状态。

引用一下系统调用 listen 的 man page 中关于 backlog 参数的部分:

The behavior of the backlog argument on TCP sockets changed with Linux 2.2. Now it specifies the queue length for completely established sockets waiting to be accepted, instead of the number of incomplete connection requests. The maxi-mum length of the queue for incomplete sockets can be set using /proc/sys/net/ipv4/tcp_max_syn_backlog. When syncookies are enabled there is no logical maximum length and this setting is ignored. See tcp(7) for more information.
If the backlog argument is greater than the value in /proc/sys/net/core/somaxconn, then it is silently truncated to that value; the default value in this file is 128. In kernels before 2.4.25, this limit was a hard coded value, SOMAX-CONN, with the value 128.

用的时候我们发现,队列的这个参数是要与业务相匹配的。由于 php 要处理业务部分,所以对每个请求的处理效率肯定要比 nginx 低。可能会出现以下几种情况:

  • 队列很大,php 处理很慢,nginx 迟迟得不到如果队列过短,前端请求得快了就容易发生丢失;如果队列过长,后端迟迟不返回数据则会造成 nginx 超时并断开与后端的连接发生错误。

实际工作中如果碰到这样的需求,我会考虑使用队列:

队列使用还应该注意这样几个问题。

http://veithen.github.io/2014/01/01/how-tcp-backlog-works-in-linux.html
http://www.cnxct.com/something-about-phpfpm-s-backlog/
http://chuansong.me/n/797172
http://blog.csdn.net/yangbodong22011/article/details/60399728
http://blog.csdn.net/yangbodong22011/article/details/60468820

2017-03-23 10:44 30
Comments
Write a Comment