我有在两个节点上运行的Kubernetes,在两个节点上部署了一个应用程序(两个Pod,每个节点一个)。
这是一个Spring Boot应用程序。它使用OpenFeign来实现服务发现性。在应用程序中,我定义了RestController,它具有一些API和从API内部调用的@Autowired @Service。
每当我对一个API发出请求时,Kubernetes都会使用某种负载平衡将流量路由到其中一个Pod,然后调用应用RestController。很好,我希望做到负载均衡。
一旦调用API并调用@Autowired @Service,就会发生问题。不知何故,这也会达到负载平衡,并且@Service的调用可能最终在另一个节点上。
这里和示例:
在代码中:
控制器:
@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的,而且由于我同时调试两个节点,所以我没有注意到这一点。
答案 0 :(得分:1)
嗯,我还没有使用过openfeign,但据我了解,它实际上只能负载均衡REST请求。
如果我的问题是对的,那么你说当REST控制器调用服务组件(在这种情况下为UserService)时,就会发出网络调用,这是不可取的。
在这种情况下,我认为,考虑以下几点将是有益的:
默认情况下,Spring boot与此级别的负载平衡无关,应该以某种方式在spring boot应用程序中对其进行配置。
这也与以下事实无关:该应用程序在Kubernetes环境中运行,这仍然只是一个Spring Boot配置。
假定您有一个UserService
接口,该接口显然没有任何负载平衡逻辑,spring boot必须将其包装到某种添加了这些功能的代理中。因此,尝试调试应用程序启动,在控制器方法中放置一个断点,并检查用户服务的实际类型是什么,再次必须是某种代理
如果3中的假设正确,那么必须在应用程序上下文中注册某种bean后处理器(可能在某些依赖项的spring.factories文件中)类。如果您将创建一些将打印所有bean的自定义方法(Bean Post Processor也是bean),则可能会看到可疑bean。