Spring Boot High Availability: Nacos Service Discovery, OpenFeign & Sentinel Resilience

This article details how to build highly available Spring Boot microservices using Nacos for service discovery and configuration, OpenFeign for declarative REST calls with load balancing, timeouts, and retries, and Sentinel for circuit breaking and fallback handling, including multi-environment isolation via namespaces and groups.

Xiaolin Talks Programming
Xiaolin Talks Programming
Xiaolin Talks Programming
Spring Boot High Availability: Nacos Service Discovery, OpenFeign & Sentinel Resilience

Why a Registry Center?

After splitting microservices, the biggest headache is how services find each other. With few services, hard‑coding IPs in config files works, but elastic scaling (Pods destroyed/recreated, VMs migrated) makes static addresses impossible. A registry center lets services register themselves on startup and consumers query the list.

What Does a Registry Center Do?

Service Registration: On startup, push IP, port, health status to the registry.

Service Discovery: Consumers pull target service instance lists and pick a healthy one.

Health Checks: The registry monitors instances and removes unhealthy ones.

Selection: Why Nacos?

Eureka (Netflix) is AP‑model, guarantees availability but may return stale data; development stopped at 2.x, Spring Cloud Netflix is in maintenance mode. It only does service discovery, requiring a separate config center.

Consul uses CP (Raft) for strong consistency, but sacrifices availability during network partitions. Its active health checks (HTTP/TCP/gRPC) are thorough, and it integrates with Consul Template and Vault for dynamic config/secrets. However, config management isn’t its core strength and adds operational complexity.

Nacos combines service discovery and config management in one system. It supports both AP (ephemeral instances via client heartbeats) and CP (persistent instances via server‑side probes) modes. If you use Spring Cloud Alibaba, Nacos is the default choice; it also works well standalone.

Setting Up Nacos Server

Standalone (Docker)

docker run -d --name nacos-server \
  -p 8848:8848 -p 9848:9848 \
  -e MODE=standalone \
  nacos/nacos-server:v2.3.2

Note: Port 9848 is the gRPC port used by Nacos 2.x clients; omitting it prevents registration. After startup, open http://localhost:8848/nacos (default user/pass: nacos / nacos).

Production Cluster with MySQL

Use MySQL for config/metadata storage and run at least three nodes. Configure conf/application.properties:

spring.datasource.platform=mysql
db.num=1
db.url.0=jdbc:mysql://xxx:3306/nacos?characterEncoding=utf8&serverTimezone=UTC
db.user=root
db.password=xxx

Start each node with MODE=cluster and NACOS_SERVERS listing all node addresses:

docker run -d --name nacos-server \
  -p 8848:8848 -p 9848:9848 \
  -e MODE=cluster \
  -e NACOS_SERVERS=10.0.0.1:8848,10.0.0.2:8848,10.0.0.3:8848 \
  nacos/nacos-server:v2.3.2

Spring Boot Integration: Registration & Discovery

Dependency Versions

Used Spring Boot 2.7.18, Spring Cloud Alibaba 2021.0.5.0. Two BOMs manage versions:

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.7.18</version>
</parent>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-dependencies</artifactId>
      <version>2021.0.8</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-alibaba-dependencies</artifactId>
      <version>2021.0.5.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

Both provider and consumer need spring-cloud-starter-alibaba-nacos-discovery and spring-boot-starter-web.

Registration Configuration

In application.yml:

spring:
  application:
    name: product-service
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
        namespace: public
        group: DEFAULT_GROUP
        metadata:
          version: v1.0
          author: dev-team
        # Multi‑NIC machines may register wrong IP; specify manually
        ip: 192.168.1.100
        port: 8080
metadata

is useful for version, environment, owner — later used for gray routing or monitoring.

Health Check Modes

Nacos uses two modes: - Ephemeral instances (default): Client heartbeats every 5 s; 15 s missed → unhealthy, 30 s → removed. Suits dynamic scaling (e.g., K8s Pods). - Persistent instances: Set ephemeral: false; server actively probes via HTTP/TCP. For long‑lived services like DB proxies.

Service Discovery Usage

Spring Cloud’s DiscoveryClient is the standard interface:

@RestController
public class DiscoveryController {
  @Autowired
  private DiscoveryClient discoveryClient;

  @GetMapping("/instances")
  public List<ServiceInstance> instances(@RequestParam String serviceId) {
    return discoveryClient.getInstances(serviceId);
  }
}

But this is only for inspection; actual calls should use OpenFeign.

OpenFeign Declarative Calls

Dependencies

Consumer adds:

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

Add @EnableFeignClients on the main class.

Writing a FeignClient

@FeignClient(name = "product-service", fallback = ProductFallback.class)
public interface ProductClient {
  @GetMapping("/product/{id}")
  ProductDTO getProduct(@PathVariable("id") Long id);
}

The name matches the target service name; OpenFeign asks Nacos for instances and LoadBalancer picks one.

Load Balancing

Since Spring Cloud 2020, Ribbon is retired; default is Spring Cloud LoadBalancer (round‑robin). Custom strategies via ServiceInstanceListSupplier, e.g., weighted:

@Bean
public ServiceInstanceListSupplier serviceInstanceListSupplier(
    ObjectProvider<LoadBalancerClientFactory> factory) {
  return ServiceInstanceListSupplier.builder()
      .withDiscoveryClient()
      .withWeighted()
      .build(factory.getIfUnique());
}

Most scenarios round‑robin suffices; avoid over‑engineering.

Timeouts & Retries

Feign defaults: connect 10 s, read 60 s — too long for production. Shorten per service:

spring:
  cloud:
    openfeign:
      client:
        config:
          default:
            connect-timeout: 2000
            read-timeout: 3000
          product-service:
            connect-timeout: 1000
            read-timeout: 5000

Retries are off by default (risk of duplicate requests unless idempotent). If needed, define a Retryer bean:

@Bean
public Retryer feignRetryer() {
  // interval 100ms, max 1000ms, max 3 attempts
  return new Retryer.Default(100, 1000, 3);
}

Warning: Retries must pair with circuit breaking; otherwise a failing service gets hammered (retry storm).

Sentinel for Circuit Breaking & Fallback

Enable Sentinel Adapter

Add dependency:

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

Configure:

feign:
  sentinel:
    enabled: true

Then specify fallback or fallbackFactory on @FeignClient.

Fallback vs FallbackFactory

Fallback — simple, no exception details:

@Component
public class ProductFallback implements ProductClient {
  @Override
  public ProductDTO getProduct(Long id) {
    return ProductDTO.builder()
        .id(id)
        .name("默认商品")
        .price(0.0)
        .build();
  }
}

Must be a Spring bean ( @Component) so Feign can find it.

FallbackFactory — access to the cause for logging/differentiated handling:

@Slf4j
@Component
public class ProductFallbackFactory implements FallbackFactory<ProductClient> {
  @Override
  public ProductClient create(Throwable cause) {
    return new ProductClient() {
      @Override
      public ProductDTO getProduct(Long id) {
        log.error("调用 product-service 失败,降级", cause);
        return ProductDTO.builder().id(id).name("降级商品").build();
      }
    };
  }
}

Then use fallbackFactory = ProductFallbackFactory.class.

Circuit Breaker Rules

Define a slow‑call ratio rule in code (or via console):

@PostConstruct
public void initDegradeRule() {
  DegradeRule rule = new DegradeRule();
  rule.setResource("GET:http://product-service/product/{id}");
  rule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
  rule.setCount(500);          // max RT 500ms
  rule.setTimeWindow(10);      // break for 10s
  rule.setSlowRatioThreshold(0.5); // slow call ratio > 50%
  DegradeRuleManager.loadRules(Collections.singletonList(rule));
}

When slow‑call ratio exceeds 50% in a statistical window, Sentinel trips for 10 s, routing directly to fallback — isolating the fault.

Nacos Multi‑Environment Isolation & Service List Management

Namespaces

Simplest isolation: create separate namespaces (dev, test, prod). Each service registers with its namespace:

spring:
  cloud:
    nacos:
      discovery:
        namespace: dev-namespace-id

Groups

Within a namespace, groups further separate services (e.g., two teams using order-service). Consumers must match the group; OpenFeign defaults to DEFAULT_GROUP.

Console Operations

Instance Online/Offline: Bring an instance online without traffic (graceful deploy), or drain traffic before offline.

Weight: Control traffic proportion; start new version at weight 1, increase after validation.

Protection Threshold: Default 0; set 0.6–0.8. When healthy instance ratio drops below, Nacos returns unhealthy instances too — prevents avalanche on few healthy nodes.

Cluster: Set cluster-name (e.g., SH) on both provider and consumer; Nacos discovery layer returns only same‑cluster instances, enforcing locality without LoadBalancer filtering.

Metadata should include version, Git commit, owner — speeds up incident diagnosis.

Compared to Spring Cloud Kubernetes: How to Choose?

If running on Kubernetes, K8s Service + DNS already provides service discovery; Pods have probes, ConfigMap handles config. Spring Cloud Kubernetes adapts DiscoveryClient and LoadBalancer, so you can skip Nacos entirely — less infrastructure to maintain. However, K8s native discovery is low‑level; fine‑grained traffic management (gray, weights) needs a service mesh like Istio, and config is scattered across ConfigMaps.

For traditional VM deployments or when you need rich service governance (multi‑env config, gray release, weight control), Nacos shines — it’s built for service governance and bundles config center, giving a unified dev experience.

Hybrid approaches exist: registration via Nacos, config via ConfigMap, or vice versa. No absolute right answer; choose what reduces operational burden.

Final Thoughts

The combo (Nacos + OpenFeign + Sentinel) isn’t a silver bullet, but it’s the most cohesive stack in Spring Cloud Alibaba. Registry solves "findability", load balancing solves "distribution", timeouts/retries solve "resilience", circuit breaking solves "fault isolation". Each layer done right gives a baseline of high availability.

Remember: this is just the foundation. Production HA also demands monitoring, alerting, rate limiting, and degradation strategies. Don’t assume Nacos alone guarantees peace of mind.

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.

microservicesHigh AvailabilityService DiscoveryNacosSpring BootSentinelOpenFeignCircuit Breaker
Xiaolin Talks Programming
Written by

Xiaolin Talks Programming

Focuses on sharing original technical insights. Senior architect at a top tech company with years of experience in technical architecture and management, and extensive interview experience. Offers one-on-one technical coaching, guiding you from beginner to architecture design to technical management. Follow for free learning resources. Free one-on-one interview coaching to help you land offers quickly.

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.