Spring Cloud Ribbon client-side load balancer - spring-boot

I have a question for load balancing in scope of Spring and Ribbon.
I have Microservices architecture with several services. Let's say services: A, B, C and D. All of the services are deployed in the cloud.
In front of the services stays LB that forwards requests to the corresponding service.
All of the services are implemented in Spring Boot.
Docker images are created per each service.Each service is containerised. In my local setup I am able to start all of my services in my local kubernetes cluster. For example:
kubectl get deployment
will result in:
NAME READY UP-TO-DATE AVAILABLE AGE
A 1/1 1 1 9h
B 2/2 2 2 59m
C 1/1 1 1 9h
....
Running in K8S service B can access service A, C or any other service in the namespace with:
public String getResponseFromService() {
return this.restTemplate.getForObject("http://service-a:8080/deals", String.class);
}
If I have N number of instances of service A, a round-robin rule by default is activated and random server is fetched each time when node B invokes service A.
Question:
Does it mean that k8s itself acts as Load Balancer and redirects the requests that are coming from node B to service A to one of the instances?
If the above is true, why I at all need Ribbon client LB. I know that it uses discovery client in order to check with k8s which are registered services in service registry, but if I do not care about the registry do I need the ribbon at all?
I need several instances per each service and communication between services through single endpoint (as example above).
Apologies for the question but I am pretty new to Spring Cloud Kubernete. I read a lot but still can not get this part.
Thanks in advance!

Related

Spring boot application registers same instance, multipe times in consul cluster

I am trying to register a spring boot app to a consul cluster.
I have 3 node consul cluster 1 master 2 agents.
I have a load-balancer in front of 2 consul agents, so that it is HA.
In my application.yml. I ask the services to join via load-balancer
spring
cloud:
consul:
enabled: true
port: loadbalancer_port
host: http://loadbalancer
discovery:
instance-id: ${info.app.environment}:${spring.application.name}
tags:
- ${spring.profiles.active}
Now, when my service restarts it is creating a duplicate entry in consul.
I figured that, because it is being registered in 2 different agents.
Does this mean, I cant have HA consul with loadbalancer ? or should I ask the services to register to particular agents with out load-balancer?
Please help!!
Consul is designed to have a Consul client agent deployed on each server in your data center (see Consul Reference Architecture). Instead of registering services centrally, services running on a machine are registered with the local/co-located Consul agent. The agents then submit the list of services registered against them to the Consul servers, which then aggregates this info from each agent to form the service catalog. The catalog maintains the high-level view of the cluster, including which services are available, which nodes run those services, health information, etc.
TLDR; Remove the load balancer and register the services directly with the agents in order to avoid this issue where service registrations are duplicated across hosts.

What happens if one of the multiple instances of the same service registered on Eureka server goes down?

I've started building a microservice application with the netflix stack, and have been successful in registering clients with the eureka discovery server.
I want to have two instances of each client service,
and i'm wondering what happens if one instance of a client goes down. Does loadbalancing handle such situations ? If yes, then isn't eureka also acting as a failover system ?

Loadbalancing with feign and kubernetes

I am using feign, through spring feign and load balancing seems off. I have one instance of service A and 2 instances of service B. Service A calls service B through a feign client. I plotted incoming requests on service B and they all seem to hit the same node and after some time switch to the other node and all hit that node again. Not really what i want. I use kubernetes DNS to get a node.
Am i missing some part of the puzzle? does feign get the ip and use that for a while?
I am using the latest spring cloud, but am using httpclient instead of the standard client.
My spring feign annotation looks like:
#FeignClient(name = "serviceB", url="http://serviceb:8080")
where serviceb is the name of the service in kubernetes DNS.
Do you mean Pod by node?
To test your theory, you can continuously make a call to serviceb and bring one of the pods abruptly and see if the other pod gets the request!
k8s seems to follow random algorithm for load balancing - so there is a chance that it might send the request to the same pod which I also have seen when there is no enough request. When you can send multiple concurrent requests & continuously for certain duration, I have seen requests are distributed across all the pods.

Is there a way to register custom metadata for a service in K8S Service Discovery?

I have my service (spring boot java application) running in a K8S cluster with 3 replicas(pods). My use-case requires me to deploy application contexts dynamically.
And i need to know which context is deployed on which of the 3 Pods through service discovery. Is there a way to register custom metadata for a service in K8S Service Discovery, like we do in Eureka using eureka.instance.metadata-map?
In terms of Kubernetes, we have Deployments and Services.
Deployment is a description of state for ReplicaSet, which creates Pods. Pod consists of one or more containers.
Service is an abstraction which defines a logical set of Pods and a policy by which to access them.
In Eureka, you can set a configuration of Pods dynamically and reconfigure them on-fly, which does not match with Kubernetes design.
In Kubernetes, when you use 1 Deployment with 3 Replicas, all 3 Pods should be the same. It has no options or features to export any metadata for separate Pods under the Services into different groups because ReplicaSet, which contain Pods with same labels, is a group itself.
Therefore, the better idea is to use 3 different Deployments with 1 Replica for each, all of them with the same configuration. Or use some Springboot’s features, like its service discovery if you want to reload application context on-fly.

Sidecar doesn't support multiple instances of one NON-JVM app

I was able to register the single nodejs app instance using the netflix sidecar app successfully. Both nodejs and sidecar bridge app are running in Cloud foundry.
Result:
SAMPLE-NODEJS n/a (1) (1) UP (1)
When i scale the nodeJS app to 3 instances, could not see the scaled instances in Eureka service registry. It still shows 1 instance.
Can some one help me to do this....
I want to register all the instances of Nodejs app with Eureka service registry with Sidecar bridge app.
Pls.. help.
Regards
Purandhar
Sidecar, like the eureka java client is built to register only one application with the eureka server at a time. It is not a eureka proxy for multiple applications. I built a proof of concept proxy that will do what you want.
This happens because it's not your node application, which is registering to eureka, but your sidecar, which still runs in one instance.
simple solution
you scale your sidecars with your node apps. This is quite straight forward, in particular when using container based deployment. You just can craft a docker container starting both, a node instance and a sidecar.
load balancing
you can extend your sidecar application to load balance traffic to your sidecars. Then your node apps will still be shown as a single instance, but still have load balancing to scaled node instances

Resources