首页 > 运维 > linux中Cannot assign requested address的问题处理
2016
04-14

linux中Cannot assign requested address的问题处理

问题描述:

最近系统报警有类型如下错误: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 条评论

留下一个回复