Cloud Native 17 min read

Navigating Spring Cloud’s Future: Service Discovery, Config, and API Gateway Without Netflix OSS

This article explains how Spring Cloud modules formerly backed by Netflix OSS are moving to maintenance mode and shows how to replace them with Consul for service discovery and configuration, use Spring Cloud Gateway as the API gateway, and adopt Spring Cloud LoadBalancer for client‑side load balancing in modern cloud‑native microservices.

Programmer DD
Programmer DD
Programmer DD
Navigating Spring Cloud’s Future: Service Discovery, Config, and API Gateway Without Netflix OSS

If you think of Spring Cloud, the first thing that comes to mind is often Netflix OSS support. With the Spring Cloud Greenwich release, Netflix OSS modules such as Archaius, Hystrix, Ribbon, and Zuul have entered maintenance mode, meaning no new features will be added and only bug fixes and security patches will be applied. Eureka remains supported.

1. Service Discovery

Eureka is the only Netflix‑based discovery module not yet in maintenance mode, but its development is uncertain. Consul is presented as a strong alternative, offering service discovery, configuration, and key/value storage. To enable Consul discovery, add the following Maven dependency:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>

Configure the Consul client (default address is localhost:8500) in application.yml if you need to override the host and port:

spring:
  cloud:
    consul:
      host: 192.168.99.100
      port: 8500

You can test the setup with a local Consul container:

$ docker run -d --name consul -p 8500:8500 consul

Consul is maintained by HashiCorp, integrates with Spring Cloud Consul, and can also serve as a configuration server, giving it an advantage over Eureka.

2. Distributed Configuration

Netflix Archaius is now in maintenance mode, while Spring Cloud Config provides a more popular solution for externalized configuration. Consul can also act as a configuration server. Add the Consul Config starter:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-consul-config</artifactId>
</dependency>

Example bootstrap.yml to enable Consul‑backed configuration for the callme-service application:

spring:
  application:
    name: callme-service
  cloud:
    consul:
      host: 192.168.99.100
      port: 8500
      config:
        format: YAML

When using Consul as a config source, you may need to set the instance ID and enable dynamic port generation, as shown in the accompanying screenshots.

3. API Gateway

Spring Cloud Netflix Zuul has been superseded by Spring Cloud Gateway, which runs on Netty and cannot be used with traditional servlet containers. Add the following dependencies (using the latest snapshot version):

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-consul-discovery</artifactId>
  <version>2.2.0.BUILD‑SNAPSHOT</version>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-consul-config</artifactId>
  <version>2.2.0.BUILD‑SNAPSHOT</version>
</dependency>
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-gateway</artifactId>
  <version>2.2.0.BUILD‑SNAPSHOT</version>
</dependency>

Gateway routes can be defined in Consul’s key/value store as YAML. A sample route configuration that integrates with service discovery:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: caller-service
          uri: lb://caller-service
          predicates:
            - Path=/caller/**
          filters:
            - RewritePath=/caller/(?.*), /${path}
        - id: callme-service
          uri: lb://callme-service
          predicates:
            - Path=/callme/**
          filters:
            - RewritePath=/callme/(?.*), /${path}

4. Client Load Balancer

Ribbon remains the default HTTP client load balancer in Spring Cloud Commons 2.2.0, but Spring Cloud LoadBalancer is slated to replace it. Add the LoadBalancer starter:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-loadbalancer</artifactId>
  <version>2.2.0.BUILD‑SNAPSHOT</version>
</dependency>

Exclude the old Netflix modules when using Consul discovery:

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-consul-discovery</artifactId>
  <version>2.2.0.BUILD‑SNAPSHOT</version>
  <exclusions>
    <exclusion>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-netflix-core</artifactId>
    </exclusion>
    <exclusion>
      <groupId>com.netflix.ribbon</groupId>
      <artifactId>ribbon</artifactId>
    </exclusion>
    ...
  </exclusions>
</dependency>

Load‑balancer configuration class example:

@SpringBootApplication
@LoadBalancerClients({
  @LoadBalancerClient(name = "callme-service", configuration = ClientConfiguration.class)
})
public class CallerApplication {
  public static void main(String[] args) {
    SpringApplication.run(CallerApplication.class, args);
  }

  @Bean
  RestTemplate template() {
    return new RestTemplate();
  }
}

public class ClientConfiguration {
  @Bean
  RoundRobinLoadBalancer roundRobinContextLoadBalancer(LoadBalancerClientFactory clientFactory, Environment env) {
    String serviceId = clientFactory.getName(env);
    return new RoundRobinLoadBalancer(serviceId, clientFactory.getLazyProvider(serviceId, ServiceInstanceSupplier.class), -1);
  }
}

Caller controller that uses the load balancer to invoke callme-service:

@RestController
@RequestMapping("/caller")
public class CallerController {
  @Autowired Environment environment;
  @Autowired RestTemplate template;
  @Autowired LoadBalancerClientFactory clientFactory;

  @GetMapping
  public String call() {
    RoundRobinLoadBalancer lb = clientFactory.getInstance("callme-service", RoundRobinLoadBalancer.class);
    ServiceInstance instance = lb.choose().block().getServer();
    String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/callme";
    String response = template.getForObject(url, String.class);
    return "I'm Caller running on port " + environment.getProperty("local.server.port") + " calling-> " + response;
  }
}

5. Summary

The sample system consists of two instances of callme-service and one instance of caller-service. The caller uses Spring Cloud LoadBalancer to discover available callme-service instances. An API gateway (Spring Cloud Gateway) hides the internal topology and forwards external requests on port 8080 to the appropriate downstream services. After startup, all services register with the Consul node, and you can access the caller endpoint via http://localhost:8080/caller. The full source code is available at GitHub .

Original link: https://piotrminkowski.wordpress.com/2019/04/05/the-future-of-spring-cloud-microservices-after-netflix-era/ Author: Piotr Mińkowski Translator: Yunooa
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 discoveryapi-gatewayConsulSpring CloudLoad Balancer
Programmer DD
Written by

Programmer DD

A tinkering programmer and author of "Spring Cloud Microservices in Action"

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.