Spring Cloud Eureka Service Discovery: Server and Client Setup with Ribbon and Feign

This article demonstrates how to configure a Spring Cloud Eureka server and multiple client applications, covering dependency inclusion, YAML configuration, service startup, testing, and three consumption methods—DiscoveryClient, Ribbon‑enabled RestTemplate, and Feign—complete with runnable code examples.

Top Architect
Top Architect
Top Architect
Spring Cloud Eureka Service Discovery: Server and Client Setup with Ribbon and Feign

The article explains how to use Spring Cloud Eureka for service registration and discovery in a micro‑service architecture, providing step‑by‑step instructions for both the server side and three client consumption patterns.

Service Test Environment

Testing reveals that Netflix Eureka is employed as the service registry.

1. Add Eureka dependencies

<!-- eureka server -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<!-- client -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

2. Modify configuration files

Server configuration (application.yml)

eureka:
  instance:
    hostname: eureka9001.com # server instance name
    instance-id: eureka9001
  client:
    register-with-eureka: false   # do not register itself
    fetch-registry: false          # do not fetch other registries
    service-url:
      defaultZone: http://127.0.0.1:9001

Client 1 configuration

server:
  port: 8002
spring:
  application:
    name: licensingservice
eureka:
  instance:
    instance-id: licensing-service-8002
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://127.0.0.1:9001/eureka/

Client 2 configuration (identical to client 1)

server:
  port: 8002
spring:
  application:
    name: licensingservice
eureka:
  instance:
    instance-id: licensing-service-8002
    prefer-ip-address: true
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://127.0.0.1:9001/eureka/

3. Start services

Eureka server main class

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerPort9001_App {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerPort9001_App.class, args);
    }
}

Client (license service) main class

@SpringBootApplication
@RefreshScope
@EnableEurekaClient
public class LicenseApplication_8002 {
    public static void main(String[] args) {
        SpringApplication.run(LicenseApplication_8002.class, args);
    }
}

4. Test

Open http://127.0.0.1:9001 in a browser to view the registered services and their instances.

Consumer

1. DiscoveryClient method

Enable Eureka client and use DiscoveryClient to obtain the first instance of licensingservice.

@SpringBootApplication
@EnableEurekaClient
public class ConsumerApplication_7002 {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication_7002.class, args);
    }
}

@Component
public class ConsumerDiscoveryClient {
    @Autowired
    private DiscoveryClient discoveryClient;

    public ServiceInstance getServiceInstance() {
        List<ServiceInstance> serviceInstances = discoveryClient.getInstances("licensingservice");
        if (serviceInstances.isEmpty()) return null;
        return serviceInstances.get(0);
    }

    public String getUrl(String url) {
        ServiceInstance serviceInstance = getServiceInstance();
        if (serviceInstance == null) throw new RuntimeException("404 ,NOT FOUND");
        return String.format(url, serviceInstance.getUri().toString());
    }
}

@RestController
@RequestMapping("test")
public class TestController {
    private RestTemplate restTemplate = new RestTemplate();
    @Autowired
    private ConsumerDiscoveryClient consumerDiscoveryClient;

    @RequestMapping("/getAllEmp")
    public List<Emp> getAllLicense(){
        String url = consumerDiscoveryClient.getUrl("%s/test/getAllEmp");
        return restTemplate.getForObject(url, List.class);
    }
}

2. Ribbon‑enabled RestTemplate

Define a load‑balanced RestTemplate bean and a custom round‑robin rule.

// specify load‑balancing algorithm
@Bean
public IRule iRule() {
    return new RoundRobinRule();
}

@Bean
@LoadBalanced // creates a RestTemplate that supports Ribbon
public RestTemplate restTemplate() {
    return new RestTemplate();
}

@RestController
@RequestMapping("rest")
public class ConsumerRestController {
    @Autowired
    private RestTemplate restTemplate;
    private static final String SERVICE_URL_PREFIX = "http://LICENSINGSERVICE";

    @RequestMapping("/getById")
    public Emp getById(Long id) {
        MultiValueMap<String, Object> paramMap = new LinkedMultiValueMap<>();
        paramMap.add("id", id);
        return restTemplate.postForObject(SERVICE_URL_PREFIX + "/test/getById", paramMap, Emp.class);
    }
}

3. Feign client method

Add the Feign starter dependency and declare a Feign interface.

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
@FeignClient(value = "LICENSINGSERVICE", fallbackFactory = ServiceImp.class)
public interface ServiceInterface {
    @RequestMapping("/test/getById")
    Emp getById(@RequestParam("id") Long id);

    @RequestMapping("/test/getLicenseById")
    License getLicenseById(@RequestParam("id") Long id);

    @RequestMapping("/test/getAllEmp")
    List<Emp> getAllLicense();
}

@Component
public class ServiceImp implements FallbackFactory<ServiceInterface> {
    @Override
    public ServiceInterface create(Throwable throwable) {
        return new ServiceInterface() {
            @Override
            public Emp getById(Long id) {
                Emp emp = new Emp();
                emp.setName("i am feign fallback create");
                return emp;
            }
            @Override
            public License getLicenseById(Long id) { return null; }
            @Override
            public List<Emp> getAllLicense() { return null; }
        };
    }
}

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class Consumer_feign_Application_7004 {
    public static void main(String[] args) {
        SpringApplication.run(Consumer_feign_Application_7004.class, args);
    }
}

@RestController
@RequestMapping("rest")
public class ConsumerRestController {
    @Autowired
    private ServiceInterface serviceInterface;
    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping("/getById")
    public Emp getById(Long id) {
        return serviceInterface.getById(id);
    }
}

All three consumption approaches are tested: the DiscoveryClient returns the first instance, Ribbon distributes requests round‑robin across instances, and Feign simplifies the client code while providing graceful fallback handling.

Finally, the author invites readers to discuss, ask questions, and join a community group for further learning.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Microservicesservice discoveryfeigneurekaSpring CloudRibbon
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.