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. jvm参数与生产配置

    堆内存分配:JVM初始分配的内存由-Xms指定,默认是物理内存的1/64JVM最大分配的内存由-Xmx指定,默认是物理内存的1/4默认空余堆内存小于40%时,JVM就会增大堆直到-Xmx的最大限制:空 ...

  2. copy/b一个隐藏文件的小技巧

    首先找一张图片 再放一个我们想隐藏的东西 压缩一下 新建txt文本文件b.txt,输入这段代码 copy/b namei.jpg + a.rar namei2.jpg 保存,将文件名改为b.bat 双 ...

  3. 删除list列表中的某一个元素的多种方法

    当我们在处理业务的时候,很多情况下数据都要进行一层层的过滤,最近需要给一个列表中去除不符合条件的元素, 本来觉着挺简单的,Google了下发现很多方法都是旧方法,根本不符合我的需求. 于是参考着网上的 ...

  4. 「刷题笔记」哈希,kmp,trie

    Bovine Genomics 暴力 str hash+dp 设\(dp[i][j]\)为前\(i\)组匹配到第\(j\)位的方案数,则转移方程 \[dp[i][j+l]+=dp[i-1][j] \] ...

  5. SpringBoot中的Tomcat是如何启动的?

    <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>s ...

  6. k8s 部署 Java 项目

    前几天安装了 k8s 并测试了自动伸缩功能(HPA),今天来部署一个简单的 Java 应用到 k8s. 开始之前需要先安装一下 ingress 插件.ingress 作为 k8s 的流量入口,有多种实 ...

  7. PyQt(Python+Qt)学习随笔:QColumnView的resizeGripsVisible属性

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 QColumnView在一个视图中展示多个列表,每个下级列表是上一个列表的数据项的分支, QColu ...

  8. PyQt(Python+Qt)学习随笔:实现toolButton与Action的关联

    在Qt Designer中,如果创建的窗口为主窗口QMainWindow类型,可以通过<PyQt(Python+Qt)学习随笔:Qt Designer中怎么给toolBar添加按钮 >介绍 ...

  9. ADF 第一篇:Azure Data Factory介绍

    Azure Data Factory(简写 ADF)是Azure的云ETL服务,简单的说,就是云上的SSIS.ADF是基于云的ETL,用于数据集成和数据转换,不需要代码,直接通过UI(code-fre ...

  10. JS "&&"操作符妙用

    首先来了解一下 "&&"操作符的工作原理: "&&"连接两个表达式,当两侧表达式都为真时,返回TRUE.有一个为假则返回FALS ...