0

I have Kubernetes running on two nodes and one application deployed on the two nodes (two pods, one per node).

It's a Spring Boot application. It uses OpenFeign for service discoverability. In the app i have a RestController defined and it has a few APIs and an @Autowired @Service which is called from inside the APIs.

Whenever i do a request on one of the APIs Kubernetes uses some sort of load-balancing to route the traffic to one of the pods, and the apps RestController is called. This is fine and i want this to be load-balanced.

The problem happens once that API is called and it calls the @Autowired @Service. Somehow this too gets load-balanced and the call to the @Service might end up on the other node.

Heres and example:

  • we have two nodes: node1, node2
  • we make a request to node1's IP address.
    • this might get load-balanced to node2 (this is fine)
  • node1 gets the request and calls the @Autowired @Service
  • the call jumps to node2 (this is where the problem happens)

And in code:
Controller:

 @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:

@Service
class UserService {
  fun getUser(userId: String) : User {
   println(System.getEnv("hostIP")) //123.45.67.02
   ...
  }
}

I want the load-balancing to happen only on the REST requests not the internal calls of the app to its @Service components. How would i achieve this? Is there any configuration to the way Spring Boot's @service components operate in Kubernetes clusters? Can i change this?

Thanks in advance.

Edit:
After some debugging i found that It wasn't the Service that was load balanced to another node but the initial http request. Even though the request is specifically send to the url of node1... And since i was debugging both nodes at the same time, i didn't notice this.

  • The binding of dependency in spring boot happens at application startup. What do you mean by "the call jumps to node2 ". Have you logged the flow of control inside the pod to see what is happening. Also please add the source for your controller. – asolanki Oct 22 '19 at 03:33
  • Yes the binding happens on start up. I have the node ips as environment variables. Whenever i debug i put a break point in the controller and the service. The ip in the controller is lets say 123.45.67.01 and once i get to the breakpoint in the service the ip is 123.45.67.02. So the controller code executes on node1 and the service on node2. This is so wierd and it should happen... ill put an example code in few minutes – Oliver Tasevski Oct 22 '19 at 14:34

1 Answers1

1

Well, I haven't used openfeign, but in my understanding it can loadbalance only REST requests indeed.

If I've got your question right, you say that when the REST controller calls the service component (UserService in this case) the network call is issued and this is undesirable.

In this case, I believe, following points for consideration will be beneficial:

  1. Spring boot has nothing to do with load balancing at this level by default, it should be a configured in the spring boot application somehow.

  2. This also has nothing to do with the fact that this application runs in a Kubernetes environment, again its only a spring boot configuration.

  3. Assuming, you have a UserService interface that obviously doesn't have any load balancing logic, spring boot must wrap it into some kind of proxy that adds these capabilities. So try to debug the application startup, place a breakpoint in the controller method and check out what is the actual type of the user service, again it must be some sort of proxy

  4. If the assumption in 3 is correct, there must be some kind of bean post processor (possibly in spring.factories file of some dependency) class that gets registered within the application context. Probably if you'll create some custom method that will print all beans (Bean Post Processor is also a bean), you'll see the suspicious bean.

Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97
  • Ur right maybe the bean is beeing overwritter somewhere in the init of the app. Ill look in to it and get back to you – Oliver Tasevski Oct 23 '19 at 15:03
  • After some debugging i found that i have looked at the balancing wrongly. It wasnt the service that was load balanced but the initial http request, and because i was debugging remotly both nodes, i didnt notice this. I tought the request always went to one node. Not the case. Ill accept you answer for pointing me towards a solution. Now i have to look at the way the http requests are load balanced. Thank you. – Oliver Tasevski Oct 24 '19 at 15:45