Socket TCP相关

TCP 连接3次握手,断开连接4次握手图示

TCP.png

tcp/ip协议listen函数中backlog参数的含义

backlog.png

1、client发送SYN到server,将状态修改为SYN_SEND,如果server收到请求,则将状态修改为SYN_RCVD,并把该请求放到syns queue队列中。
2、server回复SYN+ACK给client,如果client收到请求,则将状态修改为ESTABLISHED,并发送ACK给server。
3、server收到ACK,将状态修改为ESTABLISHED,并把该请求从syns queue中放到accept queue。

在linux系统内核中维护了两个队列:syns queue和accept queue

syns queue
用于保存半连接状态的请求,其大小通过/proc/sys/net/ipv4/tcp_max_syn_backlog指定,一般默认值是512,不过这个设置有效的前提是系统的syncookies功能被禁用。互联网常见的TCP SYN FLOOD恶意DOS攻击方式就是建立大量的半连接状态的请求,然后丢弃,导致syns queue不能保存其它正常的请求。

accept queue
用于保存全连接状态的请求,其大小通过/proc/sys/net/core/somaxconn指定,在使用listen函数时,内核会根据传入的backlog参数与系统参数somaxconn,取二者的较小值。

在Linux下,backlog指定的是complete queue的大小,而incomplete queue的大小可以由系统管理员在 /proc/sys/net/ipv4/tcp_max_syn_backlog下进行统一配置。

如果accpet queue队列满了,server将发送一个ECONNREFUSED错误信息Connection refused到client。


[为何PHP5.5.6中fpm backlog Changed default listen() backlog to 65535]

其中理由是“backlog值为65535太大了。会导致前面的nginx(或者其他客户端)超时”,而且提交者举例计算了一下,假设FPM的QPS为5000,那么65535个请求全部处理完需要13s的样子。但前端的nginx(或其他客户端)已经等待超时,关闭了这个连接。当FPM处理完之后,再往这个SOCKET ID 写数据时,却发现连接已关闭,得到的是“error: Broken Pipe”,在nginx、redis、apache里,默认的backlog值兜是511。故这里也建议改为511

backlog的定义是已连接但未进行accept处理的SOCKET队列大小,已是(并非syn的SOCKET队列)。如果这个队列满了,将会发送一个ECONNREFUSED错误信息给到客户端,即 linux 头文件 /usr/include/asm-generic/errno.h中定义的“Connection refused”,(如果协议不支持重传,该请求会被忽略)

在linux 2.2以前,backlog大小包括了半连接状态和全连接状态两种队列大小。linux 2.2以后,分离为两个backlog来分别限制半连接SYN_RCVD状态的未完成连接队列大小跟全连接ESTABLISHED状态的已完成连接队列大小。互联网上常见的TCP SYN FLOOD恶意DOS攻击方式就是用/proc/sys/net/ipv4/tcp_max_syn_backlog来控制的,可参见《TCP洪水攻击(SYN Flood)的诊断和处理》。

在使用listen函数时,内核会根据传入参数的backlog跟系统配置参数/proc/sys/net/core/somaxconn中,二者取最小值,作为“ESTABLISHED状态之后,完成TCP连接,等待服务程序ACCEPT”的队列大小。在kernel 2.4.25之前,是写死在代码常量SOMAXCONN,默认值是128。在kernel 2.4.25之后,在配置文件/proc/sys/net/core/somaxconn (即 /etc/sysctl.conf 之类 )中可以修改。我稍微整理了流程图,如下:


uwsgi 启动的时候listen 设置大于128是失败的,报错:

Listen queue size is greater than the system max net.core.somaxconn (128).

这个值是来自 :
cat /proc/sys/net/core/somaxconn
128

  • 查看进程的backlog是多大
    Send-Q就是backlog大小
> ss -tl
State       Recv-Q Send-Q                       Local Address:Port                           Peer Address:Port 
LISTEN      0      128                                      *:8011                                      *:*       
LISTEN      0      128                              127.0.0.1:11211                                     *:*       
LISTEN      0      128                                      *:8012                                      *:*       
LISTEN      0      10                                       *:9005                                      *:*       
LISTEN      0      128                                      *:8013                                      *:*       
LISTEN      0      5                                        *:9006                                      *:*       
LISTEN      0      128                              127.0.0.1:2222                                      *:*   

有的进程不是监听端口IP的,是监听unix socket
所以用下面命令可以找到,进程监听的socket以及它的backlog是多少

ss -pl|grep owan
u_str  LISTEN     0      13     /tmp/owan_web.sock 27171486               * 0 
# 我设置了owan_web.sock的listen backlog是13 ,这里正确显示了

sudo netstat -a -p --unix|grep owan
unix  2      [ ACC ]     STREAM     LISTENING     27171486 5424/uwsgi          /tmp/owan_web.sock
unix  3      [ ]         STREAM     CONNECTING    0        -                   /tmp/owan_web.sock
unix  3      [ ]         STREAM     CONNECTING    0        -                   /tmp/owan_web.sock
unix  3      [ ]         STREAM     CONNECTING    0        -                   /tmp/owan_web.sock
unix  3      [ ]         STREAM     CONNECTING    0        -                   /tmp/owan_web.sock
# 也是类似根据pid查询进程的状态, 多个请求的情况下,有CONNECTED, CONNECTING等状态

Linux 2.4.7 a backlog of 3 given to listen() results in up to 6 connections being queued.
经测试:当uwsgi 监听的时unix sockets时候, listen 的backlog设置成5的话, 用ab压测并发数是不可以超过5+3
否认会报错:

 connect() to unix:/tmp/owan_web.sock failed (11: Resource temporarily unavailable) while connecting to upstream

ab -c 132 -n 1000 http://runmo.ouwan.com/mobi/essayDetail/?id=3
压测结果:挺正常的

Server Software:        nginx/1.4.6
Server Hostname:        mo.ouwan.com
Server Port:            80

Document Path:          /mobi/essayDetail/?id=3
Document Length:        29903 bytes

Concurrency Level:      130
Time taken for tests:   2.668 seconds
Complete requests:      122
Failed requests:        0
Total transferred:      3666466 bytes
HTML transferred:       3648166 bytes
Requests per second:    45.72 [#/sec] (mean)
Time per request:       2843.376 [ms] (mean)
Time per request:       21.872 [ms] (mean, across all concurrent requests)
Transfer rate:          1341.83 [Kbytes/sec] received

但是当uwsgi 监听的是端口IP的时候,runserver 的backlog默认5, ab压测可以远远超过5


nginx 高并发优化
系统内核层面:
net.core.somaxconn = 4096 允许等待中的监听
net.ipv4.tcp_tw_recycle = 1 tcp连接快速回收
net.ipv4.tcp_tw_reuse = 1 tcp连接重用
net.ipv4.tcp_syncookies = 0 不抵御洪水攻击
ulimit -n 30000

Nginx层面:
解决: nginx.conf 下面: work_connection 加大
worker_connections 10240;
Worker_rlimit_nofiles 10000;
Keepalive_timeout 0;


web 服务器使用什么并发策略,是影响最大并发数的关键


uwsgi: your server socket listen backlog is limited to 100 connections

Note that a "listen backlog" of 100 connections doesn't mean that your server can only handle 100 simultaneous (or total) connections - this is instead dependent on the number of configured processes or threads. The listen backlog is a socket setting telling the kernel how to limit the number of outstanding (as yet unaccapted) connections in the listen queue of a listening socket. If the number of pending connections exceeds the specified size, new ones are automatically rejected. A functioning server regularly servicing its connections should not require a large backlog size.


upstream prematurely closed connection while reading response header from upstream,
104: Connection reset by peer


http://www.cppblog.com/thisisbin/archive/2010/02/07/107444.html
http://www.jianshu.com/p/e6f2036621f4
https://stackoverflow.com/questions/12893379/listen-queue-length-in-socket-programing-in-c


UNIX Domain Socket 与 TCP/IP Socket 对比

socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket。
虽然网络socket也可用于同一台主机的进程间通讯(通过loopback地址127.0.0.1),
但是UNIX Domain Socket用于IPC更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。
UNIX域套接字与TCP套接字相比较,在同一台主机的传输速度前者是后者的两倍。
这是因为,IPC机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。
UNIX Domain Socket也提供面向流和面向数据包两种API接口,类似于TCP和UDP,但是面向消息的UNIX Domain Socket也是可靠的,消息既不会丢失也不会顺序错乱。

A UNIX socket is an inter-process communication mechanism that allows bidirectional data exchange between processes running on the same machine.

IP sockets (especially TCP/IP sockets) are a mechanism allowing communication between processes over the network.
In some cases, you can use TCP/IP sockets to talk with processes running on the same computer (by using the loopback interface).

UNIX domain sockets know that they’re executing on the same system, so they can avoid some checks and operations (like routing);
which makes them faster and lighter than IP sockets.
So if you plan to communicate with processes on the same host, this is a better option than IP sockets.

strace 跟踪进程命令

strace -tfp PID
strace -o output.txt cmd
strace -o output.txt -fp PID
 #统计命令各个系统条用的次数
strace -c  command
# 通过使用-o选项可以把strace命令的输出结果保存到一个文件中。
sudo strace -o process_strace -p 3229
# strace命令的-e选项仅仅被用来展示特定的系统调用(例如,open,write等等)
strace -e open cat dead.letter

命令相关:1.https://lesliezhu.github.io/2014/06/19/strace%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E8%BF%9B%E7%A8%8B%E7%9A%84%E7%B3%BB%E7%BB%9F%E8%B0%83%E7%94%A8/
2.https://linux.cn/article-3935-1.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 151,688评论 1 330
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 64,559评论 1 273
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 101,749评论 0 226
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 42,581评论 0 191
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 50,741评论 3 271
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 39,684评论 1 192
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,122评论 2 292
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 29,847评论 0 182
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 33,441评论 0 228
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 29,939评论 2 232
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,333评论 1 242
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 27,783评论 2 236
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,275评论 3 220
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 25,830评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,444评论 0 180
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 34,553评论 2 249
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 34,618评论 2 249

推荐阅读更多精彩内容

  • 一、 概述UNIX Domain Socket是在socket架构上发展起来的用于同一台主机的进程间通讯(IPC)...
    chandarlee阅读 6,611评论 0 51
  • NAME dnsmasq - A lightweight DHCP and caching DNS server....
    ximitc阅读 2,636评论 0 0
  • 隔着窗, 贪恋你睡意的侧脸。 看见光, 唤出你如玉的笑颜。 掌心水, 星星汇成的溪泉。 眼浸泪, 万般回眸后倔强的...
    翔舞之笑阅读 222评论 0 1
  • 平生非喜律, 为爱做新诗。 但有相思韵, 何惜笔墨痴。
    爱花痴阅读 213评论 0 0
  • 去上海自然博物馆参观的时候看到这一面墙。 相信了解拼布的人都会想起一个词,“玻璃彩绘”。 彩绘的玻璃最早运用于教堂...
    百合手工阅读 207评论 1 3