1. 错误

今天项目中出现了大量的java.net.ConnectException: Cannot assign requested address (connect failed)

错误。

刚开始以为是服务提供方的服务器报出来的错误,还和对方怼了几句。但是之后在网上搜索之后发现,这个是客户端机器的问题:

这个错误的报出是由于客户端服务器的出口socket端口被占用完了,没有办法对新的请求进行分配端口,就会出现这种错误。

排查当时的情况,确实有大量的依赖服务调用出现。

但是这种情况不是每天都有,而是偶发性的。所以和我们自己的服务有关系,由于业务原因导致了端口被占用完了。

2. 原因

google 之后发现了一个大致的原因:建立TCP连接之后,断开连接的一方会进入 TimeWait状态,此时这个连接是不可以

复用的。而连接是由4元组(localIP/port,serverIp/port)来唯一确定一个连接,对于一个客户端来说,server端的都确定了(单台服务情况),

而本机ip不会变化,所以能变化的只有服务器提供的临时端口。

我们知道端口是由2个字节描述的,也就是范围是65525.再加上服务器有一些默认端口被占用,可供临时分配的端口大概会在2w+左右ref

当短时间大量请求出现的时候,端口是有占满的可能,此时就会报错误,ref.

既然请求都结束了,为什么还需要占用端口呢,有没有办法复用这些端口呢?

3. 一种解决途径

答案是肯定的,unix 有一个参数 SO_REUSEADDR设置 处于 Time_wait状态的端口可以被复用,如下是翻译:

这个socket 参数是用来告诉内核,当一个端口处于Time_wait 状态的时候,依然可以使用这个端口。但是如果端口不是这个状态,那么还是会

得到一个错误:地址被占用。这个参数可以很方便的使用在很快结束并又重新建立连接的服务。

但是你需要知道,如果有其他不可预知的数据进来时,会破坏你的服务。但是这个可能性很低。

Michael Hunter (mphunter@qnx.com) 指出过:网络5元组用于确定连接唯一性。这个参数仅仅说明你可以复用本地的地址。连接还需要保证

网络连接的唯一性。也就是说如果你访问的目标服务器还是同一台,那么连接还会是同一个;如果不是同一台,那么不是同一个连接。

危险仅出现在当一个断开的连接还是在使用中,同一台客户端调用了同一个服务端,此时就会出现使用同一个连接的情况。也就得到意想不到的数据。

这也就是为什么有 Time_wait 状态出现的原因,为了保证短时间内连接不可复用。

原文如下

What exactly does SO_REUSEADDR do?

This socket option tells the kernel that even if this port is busy (in

the TIME_WAIT state), go ahead and reuse it anyway. If it is busy,

but with another state, you will still get an address already in use

error. It is useful if your server has been shut down, and then

restarted right away while sockets are still active on its port. You

should be aware that if any unexpected data comes in, it may confuse

your server, but while this is possible, it is not likely.



It has been pointed out that "A socket is a 5 tuple (proto, local

addr, local port, remote addr, remote port). SO_REUSEADDR just says

that you can reuse local addresses. The 5 tuple still must be

unique!" by Michael Hunter (mphunter@qnx.com). This is true, and this

is why it is very unlikely that unexpected data will ever be seen by

your server. The danger is that such a 5 tuple is still floating

around on the net, and while it is bouncing around, a new connection

from the same client, on the same system, happens to get the same

remote port. This is explained by Richard Stevens in ``2.7 Please

explain the TIME_WAIT state.''.

Cannot assign requested address 和 SO_REUSEADDR 参数的更多相关文章

  1. Cannot assign requested address出现的原因及解决方案

    今天使用python多线程请求服务时,出现Cannot assign requested address错误 网上找了下原因,大致上是由于客户端频繁的连服务器,由于每次连接都在很短的时间内结束,导致很 ...

  2. TIME_WAIT引起Cannot assign requested address报错

    1.  问题描述 有时候用redis客户端(php或者java客户端)连接Redis服务器,报错:"Cannot assign requested address." 原因是客户端 ...

  3. php连接memcahed出现Cannot assign requested address (99)的解决方法

    今天在将服务器合并后,发现php偶尔会报出 Server *.*.*.* (tcp *****) failed with: Cannot assign requested address (99) 的 ...

  4. Dubbo广播模式下报错:Can't assign requested address解决办法

    原因: 尝试使用Dubbo的multicast模式,发现一运行就报Can't assign requested address的错误,造成这种原因的主要是系统中开启了IPV6协议(比如window7) ...

  5. Cannot assign requested address (connect failed)

    压测时,应用服务器报错:Cannot assign requested address (connect failed) 经检查,由于应用服务器,频繁发起http请求,由于每次连接都在很短的时间内结束 ...

  6. [译]Python - socket.error: Cannot assign requested address

    原文来源: https://stackoverflow.com/questions/48306528/python-socket-error-cannot-assign-requested-addre ...

  7. 使用Java进行udp-demo编程时碰到的consumer和producter无法连接并报出“java.net.SocketException: Can't assign requested address”问题

    在用Java编写了一个udp生产者和消费者的demo时,在生产者启动的时候会抛出异常 java.net.SocketException: Can't assign requested address ...

  8. Cannot assign requested address的解决办法

    今天想试一下redis,写了个程序,对redis连续进行100000访问,却出现以了Cannot assign requested address的问题,我起先是以为是redis的问题(可能承受不了这 ...

  9. Nginx无法监听虚拟VIP的问题报:99: Cannot assign requested address

    99: Cannot assign requested address #本地网卡上没有10.0.0.3这个IPNginx就会报错: [root@lb01 conf]# /application/ng ...

随机推荐

  1. [笔记] dumpsys meminfo数据与smaps文件对应关系

    通过cat /proc/$PID/smaps可以查看进程内存的详细映射情况.详细解析可以参考kernel的文档/Documentation/filesystems/proc.txt 如果我们的Andr ...

  2. 什么,kafka能够从follower副本读数据了 —kafka新功能介绍

    最近看了kafka2.4新版本的一些功能特性,不得不说,在kafka2.0以后,kafka自身就比较少推出一些新的feature了,基本都是一些修修补补的东西.倒是kafka connect和kafk ...

  3. Docker一些基本操作

    1.停止所有的container,这样才能够删除其中的images: docker stop $(docker ps -a -q) 如果想要删除所有container的话再加一个指令: docker ...

  4. 发现了一个关于 gin 1.3.0 框架的 bug

    gin 1.3.0 框架 http 响应数据错乱问题排查 问题概述 客户端同时发起多个http请求,gin接受到请求后,其中一个接口响应内容为空,另外一个接口响应内容包含接口1,接口2的响应内容,导致 ...

  5. Netty 心跳处理

    传统的心跳包设计,基本上是服务端和客户端同时维护 Scheduler,然后双方互相接收心跳包信息,然后重置双方的上下线状态表.此种心跳方式的设计,可以选择在主线程上进行,也可以选择在心跳线程中进行,由 ...

  6. 使用Jmeter测试快速入门

    一 创建线程组 1.1.2.   线程组主要包含三个参数:线程数.准备时长(Ramp-Up Period(in seconds)).循环次数. 1.1.3.    线程数:虚拟用户数.一个虚拟用户占用 ...

  7. charles功能(三)弱网测试(模拟超慢网速,会导致接口数据返回超时的那种慢)

    模拟超慢网速(会导致接口数据返回超时的那种...) 设置带宽和延迟时间(毫秒) 注:可以根据下图中的翻译体会下导致网络延迟的原因: 然后打开网页回变得非常满

  8. Docker实战 | 第四篇:Docker启用TLS加密解决暴露2375端口引发的安全漏洞,被黑掉三台云主机的教训总结

    一. 前言 在之前的文章中 IDEA集成Docker插件实现一键自动打包部署微服务项目,其中开放了服务器2375端口监听,此做法却引发出来一个安全问题,在上篇文章评论也有好心的童鞋提示,但自己心存侥幸 ...

  9. 第9.1节 Python的文件打开函数open简介

    一.语法简介 函数基本使用语法:open(文件名,文件打开模式='rt') 其中: 1.文件名为可带路径的文件名,注意windows下路径的反斜杠会被作为转义符处理,因此可以采用前面再加反斜杠或使用原 ...

  10. sql black list 绕过

    Black list is so weak for you,isn't it 姿势: return preg_match("/set|prepare|alter|rename|select| ...