linux中Cannot assign requested address的问题处理
参考:https://www.phpmianshi.com/?id=109
问题描述:
最近系统报警有类型如下错误:Cannot assign requested address 主要是连接mysql时产生的错误。
分析原因:
客户端与服务端每建立一个连接,客户端一侧都会占用一个本地端口(假设没有启用SO_REUSEADDR选项),本地端口数量是有限制的(默认是net.ipv4.ip_local_port_range=32768 61000),也就是说在没设置socket的SO_REUSEADDR选项时,一台Linux服务器作为客户端(注意是作为客户端)默认只能建立大概3万个TCP连接(服务端没有这个限制),可以更改net.ipv4.ip_local_port_range增大作为客户端可发起的并发连接数,但最多不会超过65535个(服务端没有这个限制)。
当Linux服务器作为客户端频繁建立TCP短连接时,本地会可能会产生很多TIME_WAIT状态的连接,客户端侧的TIME_WAIT状态的连接会占用一个本地端口直到达到2MSL(最长分解生命期)的时间,这样会导致本地端口被暂时占用,当短连接建立速度过快时(例如做压测时),会导致Cannot assign requested address错误
当系统的内核版本小于 3.2 时:
ip_local_port_range 决定了客户端的一个 ip 可用的端口数量,即一个 ip 最多只能创建61000-32768个连接,如果要突破这个限制需要客户端机器绑定多个 ip
当系统的内核版本大于等于 3.2 时:
ip_local_port_range 决定的是 socket 四元组中的本地端口数量,即一个 ip 对同一个目标 ip+port 最多可以创建61000-32768个连接,只要目标 ip或端口不一样就可以使用相同的本地端口,不一定需要多个客户端 ip 就可以突破端口数量限制。
解决方法:
设置端口复用(复用TIME_WAIT状态的连接,稍微调大端口范围)。
打开文件 /etc/sysctl.conf,增加以下设置
net.ipv4.ip_forward = 1
net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_recycle=1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 10
net.ipv4.ip_local_port_range = 20000 61000
net.ipv4.tcp_max_tw_buckets = 200000
net.nf_conntrack_max = 524288
net.netfilter.nf_conntrack_max = 524288
net.netfilter.nf_conntrack_tcp_timeout_close_wait = 60
net.netfilter.nf_conntrack_tcp_timeout_fin_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 120
net.netfilter.nf_conntrack_tcp_timeout_established = 3600
fs.file-max=100001
运行 sysctl -p即可生效
有可能产生的问题:
稍微调大端口范围,有可能会跟系统服务预留的监听端口冲突
我们可以将服务监听的端口以逗号分隔全部添加到ip_local_reserved_ports中,TCP/IP协议栈从ip_local_port_range中随机选取源端口时,会排除ip_local_reserved_ports中定义的端口,因此就不会出现端口被占用了服务无法启动。注意他的格式可以是这种:1,2-4,10-10 详细介绍下面解释。
2个参数的官方解释:
ip_local_port_range - 2 INTEGERS Defines the local port range that is used by TCP and UDP to choose the local port. The first number is the first, the second the last local port number. If possible, it is better these numbers have different parity (one even and one odd value). Must be greater than or equal to ip_unprivileged_port_start. The default values are 32768 and 60999 respectively. ip_local_reserved_ports - list of comma separated ranges Specify the ports which are reserved for known third-party applications. These ports will not be used by automatic port assignments (e.g. when calling connect() or bind() with port number 0). Explicit port allocation behavior is unchanged. The format used for both input and output is a comma separated list of ranges (e.g. "1,2-4,10-10" for ports 1, 2, 3, 4 and 10). Writing to the file will clear all previously reserved ports and update the current list with the one given in the input. Note that ip_local_port_range and ip_local_reserved_ports settings are independent and both are considered by the kernel when determining which ports are available for automatic port assignments. You can reserve ports which are not in the current ip_local_port_range, e.g.: $ cat /proc/sys/net/ipv4/ip_local_port_range 32000 60999 $ cat /proc/sys/net/ipv4/ip_local_reserved_ports 8080,9148 although this is redundant. However such a setting is useful if later the port range is changed to a value that will include the reserved ports. Default: Empty
更多推荐
所有评论(0)