Unix / Linux

服务器端的tcp有大量TIME_WAIT怎么办

公司的群里讨论tcp的TIME_WAIT的问题。TIME_WAIT这个状态可是面试时经常问的知识点啊。
讨论的问题是:有一个服务器,它对外网提供服务,同时它作为客户端连接很多后端的其它服务器。这位同事连后端其它服务器时用了短tcp连接。结果出现了大量的tcp TIME_WAIT状态,吞吐量上不去,怎么办?

先说结论:
1. 如果该服务器要处理外网IP的入流量,那最好的办法应该是用tcp长链接改造它与后端服务器的连接。如果用中间件,比如上zeromq那更省心了。
2. 如果不想做改动,并且在应用层确认已经交互已经完成,则可以用shutdown()直接发RST结束tcp会话,而不走正常的4次挥手。查阅shutdown系统调用的文档获知如何发RST。
3. 如果该服务器不需要处理处网IP请求的话,那么,启用port reuse 即打开net.ipv4.tcp_tw_reuse不会有太大问题(如果处理外网请求就有问题,和NAT相关,见https://vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux),或者更好的,把/proc/sys/net/ipv4/tcp_fin_timeout改小,改成1或者2。让TIME_WAIT只保持很短的时间。

首先,需要知道一个tcp会话由 src_ip, src_port, dest_ip, dest_port 四元组确定。
我们公司的IDC环境中, 上述的服务器作为客户端再发起tcp连接联后端服务器,则 src_ip 固定了, dest_ip是后端服务器的ip, port是后端服务器监听端口。这样只有 src_port 是可变化的,但port只有16个bits还不能用well-known ports,这样就更少了。

再说,主动关闭时,tcp连接需要进入TIME_WAIT状态,保持两倍MSL时长,是为了处理两种情况:
1) 让当前这个会话的迷路包在网路中消失。这样不会干扰到新建的会话。
2) 确保主动关闭方的FIN-ACK包,如果丢失的话,还能重发。
1981年的TCP RFC上把MSL设成两分钟,https://tools.ietf.org/html/rfc793

Maximum Segment Lifetime, the time a TCP segment can exist in
the internetwork system. Arbitrarily defined to be 2 minutes.

MSL设置这么长,因为以前的网络环境差啊。不过现在因为移动互联网,比较差的网络状态也是非常常见的。但RFC允许实现方减少MSL值。事实上linux的MSL写死在代码中为1分钟并且不可在运行期配置。
如果tcp连接的双方都在性能高速稳定的内网中,这个MSL就太长了。

调试时,还发现如果port用完了,connect的时候内核代码会用自旋锁忙等检查port资源。有linux内核开发基础的开发者都知道spin_lock的时候是不会让出cpu的,于是cpu全被spin_lock吃掉了。一直要等到有port被释放。再后来又发现,如果scoket没有设定SO_REUSEADDR选项,则connect()系统调用会返回EADDRINUSE。

tcp的连接双方都是确定且长期的,用什么tcp短连接呢??改造吧~~~

Be the first to comment - What do you think?  Posted by zausiu - October 20, 2017 at 14:03

Categories: Network, Unix / Linux   Tags:

Linux 如何知道有哪些硬件,该装哪个驱动

Linux 如何知道有哪些硬件,该装哪个驱动

公司明文不准安装虚拟机了,被查到就是死罪。于是我在自己的笔记本上安装了Debian Linux。

结果无线网卡识别不了~~

次奥~

怎么破呢?

这么破:

# lspci

该命令列出了所有PCI总线上的硬件设备,稍微看看就能看到自己的无线网卡了。

05:00.0 Network Controller: Atheros Communication Inc. AR9287 Wireless Network Adaptor (PCI-Express)(rev 01)

注意前面的坐标05:00.0,再到/sys下面找对应哪个驱动:

find /sys | grep drivers.*05:00.0

/sys/bus/pci/drivers/ath9k/0000:05:00.0

其实,还有更简单的办法:

#lspci -v 

就搞定了。

用lsmod 和 dmesg | grep ath9k 可以看到网卡对应模块的一些信息.

再编辑 /etc/network/interface

auto wlan0

iface wlan0 inet dhcp

wpa-ssid Tencent-FreeWiFi

wpa-psk xxxxxx

最后: iwconfig wlan up

搞定!!!

Be the first to comment - What do you think?  Posted by zausiu - July 23, 2014 at 11:12

Categories: Network, Tech Articles, Unix / Linux   Tags:

怎么知道gcc搜索头文件的路径

每个C/C++程序员都知道,对于#include directive,一般,以双引号引用的头文件是程序号自定义的头文件。而用尖括号引用的头文件是系统的头文件或其它库文件。

更详细的,编译器先在当前目录找用双引号""引用的头文件,如果找不到再到系统目录找这个头文件。而对于尖括号引用的头文件,编译器就只在系统文件中搜索了。

那么,到底是在哪些目录中搜索头文件呢?

可以用cpp查看,如下:

root@vicarious:/home/kamus/projs/horoscope/boost# cpp -v
Using built-in specs.
COLLECT_GCC=cpp
Target: x86_64-linux-gnu
Thread model: posix
gcc version 4.7.2 (Debian 4.7.2-5) 
COLLECT_GCC_OPTIONS='-E' '-v' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/4.7/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu - -mtune=generic -march=x86-64
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.7/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/4.7/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/4.7/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.

 

一般编写makefile时给gcc指定 -I选项,-I的参数代表的目录是搜索系统头文件时使用的目录。可以试试# cpp -I/tmp -v 

/tmp目录会被添加为搜索系统头文件时的第一个目录。

如果想要添加搜索双引号""引用的头文件使用的目录呢,用 -iquote 选项指定更多的目录。

copyright blog.ykyi.net

Be the first to comment - What do you think?  Posted by zausiu - February 13, 2014 at 16:02

Categories: Tech Articles, Unix / Linux   Tags:

Next Page »