【问题标题】:Microservice architecture | Cannot assign requested address微服务架构 |无法分配请求的地址
【发布时间】:2017-01-07 17:11:43
【问题描述】:
我们有一个微服务架构,其中来自公共(移动应用)的单个请求在内部会导致对不同服务的 4 次 HTTP 调用。
我观察到的其中一个副作用是,在重负载下,我们开始遇到错误“无法分配请求的地址”。
运行netstat -tunp | wc -l 显示的计数约为 60k,而通常它徘徊在 3k 左右。
我似乎遇到了端口耗尽的情况。我的应用程序是使用 Apache HTTP 客户端用 Java 编写的。
解决此问题的最佳方法是什么?我想到的解决方案很少,但我不确定它是否正确:
有什么想法吗?
【问题讨论】:
-
netstat 输出中的套接字状态是什么?他们是否处于 TIME_WAIT 状态?如果是这样,另一种方法是配置 Linux 内核设置。看看那些:tcp_tw_reuse,tcp_max_tw_buckets。但是,当然,最好的方法是使用连接池和保持活动(在需要时)连接。这将使您能够控制如何管理连接的所有方面。
标签:
java
apache
http
apache-httpclient-4.x
【解决方案1】:
有几个原因可能会耗尽可用端口。 (为避免混淆,我将您的面向用户的服务器称为“应用程序”。):
- 如果您只有一个具有一个 IP 地址的应用程序实例,则从这台机器到您的四个微服务中的任何一个的最大连接数限制为临时端口的数量。默认临时端口范围因操作系统而异,但可以设置为高达 65535(所有端口都可用作临时端口,尽管这极不寻常)。
- 如果您的微服务响应正在发送
Connection: close,或者如果您的应用程序不支持保持连接,则应用程序将在每次请求后关闭 TCP 连接。当 TCP 连接关闭时,关闭端进入 TIME_WAIT for 2xMSL(请参阅RFC 1122 section 4.2.2.13)。默认 MSL 也因操作系统而异,但常见的默认值是 30 秒。这意味着应用程序将无法使用该端口与同一微服务通信 60 秒。
- 如果微服务正在关闭连接(可能是因为应用程序正在发送
Connection: close),它们将进入 TIME_WAIT,并且您可能最终导致微服务端端口耗尽。
端口耗尽的解决方案取决于上述哪种情况正在发生。这是我会尝试的:
- 启用应用程序和微服务之间的保持连接,并使用连接池。这将大大减少您的应用程序和微服务之间打开和关闭的连接数,避免由于 TIME_WAIT 导致的端口耗尽。
- 单个应用程序实例和单个微服务之间的 65k+ 并发连接很多。如果您达到此限制,您可能需要增加单个应用程序实例可用于发出请求的 IP 地址数量,可能是通过添加虚拟 IP 地址。您还可以添加应用程序实例并将它们放在负载均衡器后面。
- 您可以增加微服务可用的 IP 地址数量,并使用 DNS 循环等系统来平衡 IP 地址之间的负载。
- 您可以在操作系统级别为您的应用程序和/或微服务调整 MSL,以减少 TIME_WAIT 中的套接字数量。不过,我不推荐这个;存在潜在的负面影响,并且在几乎所有情况下,如果这是解决问题的唯一方法,您的应用程序或架构都是错误的。
我建议先从 keep-alives 和连接池开始。