Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct way to use feign with spring cloud kubernetes?

I am using Spring Cloud Kubernetes and I am trying to make feign able to send requests based on the name of the services present in kubernetes, but I can't, when I try to make a request the following error occurs:

  "timestamp": "2019-12-06T15:37:50.285+0000",
    "status": 500,
    "error": "Internal Server Error",
    "message": "com.netflix.client.ClientException: Load balancer does not have available server for client: poc-saldo",
    "trace": "java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: poc-saldo\n\tat org.springframework.cloud.openfeign.ribbon.LoadBalancerFeignClient.execute....

I tried to call other services within the cluster and the problem is the same for all of them, I did a test by going into the poc-deposit pod and doing a poc-balance curl and it works normally, so the problem is not with the poc-deposit service. balance or with kubernetes's service discovery apparently.

The project has a public profile at:

https://gitlab.com/viniciusxyz/spring-kubernetes-feign

For those who want more direct information:

My main class is as follows:

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ServiceDiscoveryApplication {

    public static void main(String[] args) {
        SpringApplication.run(ServiceDiscoveryApplication.class, args);
    }

}

My interface with feign is as follows:

@FeignClient("poc-saldo")
public interface ProxyGenerico {

    @RequestMapping(method = RequestMethod.GET)
    String getHttpResponse();

}

I can list the services available in kubernetes within the application as follows:

@RestController
public class RestTest {

    @Autowired
    private DiscoveryClient discoveryClient;

    @Autowired
    private ProxyGenerico proxyGenerico;

    @GetMapping("/services")
    public ResponseEntity<?> services()  {
        return new ResponseEntity<Object>(discoveryClient.getServices(), HttpStatus.OK);
    }

    @GetMapping("/pocsaldo")
    public ResponseEntity<?> gitlab()  {

        return new ResponseEntity<Object>(proxyGenerico.getHttpResponse(), HttpStatus.OK);
    }

}

And in this list I have several services among them the service I want to access called poc-balance, the return json looks like the following:

[

    "poc-deposito",
    "poc-saldo",
    "sonarqube",
    "sql-server-sonar",
    "zookeeper",
    "gitlab"

]

To complement the list follow my dependencies:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-kubernetes-ribbon</artifactId>
</dependency>

The discoveryClient.getInstances ("poc-saldo") command returns:

[
    {
        "instanceId": "32a4db0d-0549-11ea-8850-e0d55ef66cf8",
        "serviceId": "poc-saldo",
        "secure": false,
        "metadata": {
            "helm.sh/chart": "spring-boot-app-0.1.23",
            "port.http": "8080",
            "app.kubernetes.io/managed-by": "Tiller",
            "app.kubernetes.io/name": "poc-saldo",
            "app.kubernetes.io/instance": "banco-digital-poc-saldo",
            "app.kubernetes.io/version": "1.0"
        },
        "port": 8080,
        "host": "10.42.0.60",
        "scheme": "http://",
        "uri": "http://10.42.0.60:8080"
    }
]

Can you think of where the problem might be?

like image 841
Vinicius Santos Avatar asked Dec 06 '19 16:12

Vinicius Santos


1 Answers

Long story short, Spring Cloud Feign works perfectly fine with Spring Cloud Kubernetes as of July 2021. I've moved a Spring Cloud Feign project from using Spring Cloud Netflix to Spring Cloud Kubernetes and no change in the Feign interfaces was required. I just removed the previous Service Registry (Eureka) dependency from my build.gradle file and added:

implementation 'org.springframework.cloud:spring-cloud-starter-kubernetes-client-all'

The support for Spring Cloud LoadBalancer which is now used by Spring Cloud Feign was added to Spring Cloud Kubernetes and Ribbon was removed as of Spring Cloud 2020.0. (aka Ilford), therefore there is no need to exclude it anymore.

Beyond that, the only change required in the whole codebase was annotating the Spring Boot application class with @EnableDiscoveryClient to enable K8s-native Service Discovery:

@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class BookApplication {

Spring Cloud Feign uses Spring Cloud LoadBalancer which when running on Kubernetes leverages Discovery Client for Kubernetes to check for service instances. As a result, it only chooses from instances that are up and running. The only requirement is to align the Kubernetes service name with spring.application.name property. Just like that:

application.properties(yaml):

spring.application.name=library-book-service

combined with the following Kubernetes configuration

kubectl get svc:

NAME                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)             AGE
library-book-service       ClusterIP   10.100.200.235   <none>        8080/TCP            5d21h
like image 196
dbaltor Avatar answered Nov 14 '22 23:11

dbaltor