Kubernetes 和 Spring Boot @Service 负载均衡
Kubernetes and Spring Boot @Service load balancing
我在两个节点上安装了 Kubernetes 运行,并在这两个节点上部署了一个应用程序(两个 pods,每个节点一个)。
它是一个 Spring 启动应用程序。它使用 OpenFeign 实现服务可发现性。在应用程序中,我定义了一个 RestController,它有几个 APIs 和一个从 APIs.
内部调用的 @Autowired @Service
每当我对 API 之一发出请求时,Kubernetes 使用某种负载平衡将流量路由到 pods 之一,并调用应用程序 RestController。这很好,我希望它是负载平衡的。
一旦调用 API 并调用 @Autowired @Service,就会出现问题。这也以某种方式实现了负载平衡,并且对@Service 的调用可能会在另一个节点上结束。
此处和示例:
- 我们有两个节点:node1、node2
- 我们向节点 1 的 IP 地址发出请求。
- 这可能会对节点 2 进行负载平衡(这很好)
- node1 获取请求并调用@Autowired @Service
- 调用跳转到node2(这是问题发生的地方)
在代码中:
控制器:
@Autowired
private lateinit var userService: UserService
@PostMapping("/getUser")
fun uploadNewPC(@RequestParam("userId") userId: String): User {
println(System.getEnv("hostIP")) //123.45.67.01
return userService.getUser(userId)
}
服务:
@Service
class UserService {
fun getUser(userId: String) : User {
println(System.getEnv("hostIP")) //123.45.67.02
...
}
}
我希望负载平衡只发生在 REST 请求上,而不是应用程序对其 @Service 组件的内部调用。我将如何实现这一目标? Spring Boot 的@service 组件在Kubernetes 集群中的运行方式有没有配置?我可以更改吗?
提前致谢。
编辑:
经过一些调试后,我发现它不是负载平衡到另一个节点的服务,而是初始的 http 请求。即使请求专门发送到 node1 的 url... 而且由于我同时调试两个节点,所以我没有注意到这一点。
好吧,我没有使用过 openfeign,但据我所知,它确实只能对 REST 请求进行负载平衡。
如果我答对了你的问题,你会说当 REST 控制器调用服务组件(在本例中为 UserService)时会发出网络调用,这是不可取的。
在这种情况下,我认为以下几点的考虑会有所帮助:
Spring 引导默认情况下与此级别的负载平衡无关,它应该以某种方式在 spring 引导应用程序中配置。
这也与此应用程序在 Kubernetes 环境中运行这一事实无关,同样它只是一个 spring 启动配置。
假设,你有一个 UserService
接口,显然没有任何负载平衡逻辑,spring boot must wrap它变成某种添加这些功能的代理。所以尝试调试应用程序启动,在控制器方法中放置一个断点并检查用户服务的实际类型是什么,同样它必须是某种代理
如果 3 中的假设是正确的,则必须有某种 bean post 处理器(可能在某些依赖项的 spring.factories 文件中)class在应用程序上下文中注册。如果您创建一些自定义方法来打印所有 bean(Bean Post Processor 也是一个 bean),您可能会看到可疑的 bean。
我在两个节点上安装了 Kubernetes 运行,并在这两个节点上部署了一个应用程序(两个 pods,每个节点一个)。
它是一个 Spring 启动应用程序。它使用 OpenFeign 实现服务可发现性。在应用程序中,我定义了一个 RestController,它有几个 APIs 和一个从 APIs.
内部调用的 @Autowired @Service每当我对 API 之一发出请求时,Kubernetes 使用某种负载平衡将流量路由到 pods 之一,并调用应用程序 RestController。这很好,我希望它是负载平衡的。
一旦调用 API 并调用 @Autowired @Service,就会出现问题。这也以某种方式实现了负载平衡,并且对@Service 的调用可能会在另一个节点上结束。
此处和示例:
- 我们有两个节点:node1、node2
- 我们向节点 1 的 IP 地址发出请求。
- 这可能会对节点 2 进行负载平衡(这很好)
- node1 获取请求并调用@Autowired @Service
- 调用跳转到node2(这是问题发生的地方)
在代码中:
控制器:
@Autowired
private lateinit var userService: UserService
@PostMapping("/getUser")
fun uploadNewPC(@RequestParam("userId") userId: String): User {
println(System.getEnv("hostIP")) //123.45.67.01
return userService.getUser(userId)
}
服务:
@Service
class UserService {
fun getUser(userId: String) : User {
println(System.getEnv("hostIP")) //123.45.67.02
...
}
}
我希望负载平衡只发生在 REST 请求上,而不是应用程序对其 @Service 组件的内部调用。我将如何实现这一目标? Spring Boot 的@service 组件在Kubernetes 集群中的运行方式有没有配置?我可以更改吗?
提前致谢。
编辑:
经过一些调试后,我发现它不是负载平衡到另一个节点的服务,而是初始的 http 请求。即使请求专门发送到 node1 的 url... 而且由于我同时调试两个节点,所以我没有注意到这一点。
好吧,我没有使用过 openfeign,但据我所知,它确实只能对 REST 请求进行负载平衡。
如果我答对了你的问题,你会说当 REST 控制器调用服务组件(在本例中为 UserService)时会发出网络调用,这是不可取的。
在这种情况下,我认为以下几点的考虑会有所帮助:
Spring 引导默认情况下与此级别的负载平衡无关,它应该以某种方式在 spring 引导应用程序中配置。
这也与此应用程序在 Kubernetes 环境中运行这一事实无关,同样它只是一个 spring 启动配置。
假设,你有一个
UserService
接口,显然没有任何负载平衡逻辑,spring boot must wrap它变成某种添加这些功能的代理。所以尝试调试应用程序启动,在控制器方法中放置一个断点并检查用户服务的实际类型是什么,同样它必须是某种代理如果 3 中的假设是正确的,则必须有某种 bean post 处理器(可能在某些依赖项的 spring.factories 文件中)class在应用程序上下文中注册。如果您创建一些自定义方法来打印所有 bean(Bean Post Processor 也是一个 bean),您可能会看到可疑的 bean。