aiohttp.ClientSession 和 ClusterIp 没有负载平衡
aiohttp.ClientSession and ClusterIp not load balancing
我的 Kubernetes PODs 就像 a(pod_num=1) -> b (pod_num=2)。我在A创建一个session = aiohttp.ClientSession
连接服务B,使用CluterIp服务地址(比如http://b-svc:80)。当我尝试为 B 添加 2 pods 时,会话似乎不知道新添加的两个 pods 并且没有请求来到新添加的两个 pods.
aiohttp
有一个 TCPConnector
。默认情况下它有 10 秒的 dns 缓存超时。我试过减少或者等了很久,发现新加的pods.
没有访问日志
如果我总是创建一个新的session来发送请求,请求就会来到新添加的pods(但是aiohttp团队不建议,涉及到连接池没有被使用)
我期望的是
Requests automatically route [according to certain load balance rules which predefined by k8s] to the newly added pods when I reuse the client session.
更具体地说,A issue 的客户请求如下:
import asyncio
import aiohttp
import time
url = "http://b-svc:80/v1/hello"
async def main():
session = aiohttp.ClientSession()
for _ in range(100):
async with session.get(url) as response:
resp = await response.json()
print(resp)
time.sleep(2) # In order to make the cache invalid after 10s
if __name__ == "__main__":
asyncio.run(main())
服务器 B 仅 returns 一个 json 响应并记录每个请求。
{
"answer": "world"
}
起初,B 在 ClusterIp 地址后面只有一个 pod(假设它的 pod 索引 = 0)。当我增加 ClusterIp 地址后面的 pods 的数量时(比方说,添加 pods with index = 1, 2, 3),只有之前创建的第一个 pod(index = 0)可以接收请求[访问日志只出现在 pod 0,不会出现在其他 1、2、3。]。似乎会话没有向其他 pods.
发送请求
这个问题,作者对k8s处理持久连接的方式提出了质疑
并且从回答和优秀的文章Load balancing and scaling long-lived connections in Kubernetes,我们知道k8s不能很好的分发持久连接。在我的例子中,默认情况下保持活动状态是打开的。所以这些是持久连接。如果没有建立新的 tcp 连接,则不会发生新的分配。所以新添加的pods将不会收到请求。
在客户端禁用保持活动将解决问题。
aiohttp.ClientSession(connector=aiohttp.TCPConnector(force_close=True))
Github 问题:
我的 Kubernetes PODs 就像 a(pod_num=1) -> b (pod_num=2)。我在A创建一个session = aiohttp.ClientSession
连接服务B,使用CluterIp服务地址(比如http://b-svc:80)。当我尝试为 B 添加 2 pods 时,会话似乎不知道新添加的两个 pods 并且没有请求来到新添加的两个 pods.
aiohttp
有一个 TCPConnector
。默认情况下它有 10 秒的 dns 缓存超时。我试过减少或者等了很久,发现新加的pods.
如果我总是创建一个新的session来发送请求,请求就会来到新添加的pods(但是aiohttp团队不建议,涉及到连接池没有被使用)
我期望的是
Requests automatically route [according to certain load balance rules which predefined by k8s] to the newly added pods when I reuse the client session.
更具体地说,A issue 的客户请求如下:
import asyncio
import aiohttp
import time
url = "http://b-svc:80/v1/hello"
async def main():
session = aiohttp.ClientSession()
for _ in range(100):
async with session.get(url) as response:
resp = await response.json()
print(resp)
time.sleep(2) # In order to make the cache invalid after 10s
if __name__ == "__main__":
asyncio.run(main())
服务器 B 仅 returns 一个 json 响应并记录每个请求。
{
"answer": "world"
}
起初,B 在 ClusterIp 地址后面只有一个 pod(假设它的 pod 索引 = 0)。当我增加 ClusterIp 地址后面的 pods 的数量时(比方说,添加 pods with index = 1, 2, 3),只有之前创建的第一个 pod(index = 0)可以接收请求[访问日志只出现在 pod 0,不会出现在其他 1、2、3。]。似乎会话没有向其他 pods.
发送请求这个问题
并且从回答和优秀的文章Load balancing and scaling long-lived connections in Kubernetes,我们知道k8s不能很好的分发持久连接。在我的例子中,默认情况下保持活动状态是打开的。所以这些是持久连接。如果没有建立新的 tcp 连接,则不会发生新的分配。所以新添加的pods将不会收到请求。
在客户端禁用保持活动将解决问题。
aiohttp.ClientSession(connector=aiohttp.TCPConnector(force_close=True))
Github 问题: