Zone-Aware Service Discovery and Load Balancing with Spring Cloud and Nacos
In modern distributed systems, especially those deployed across multiple data centers or availability zones (e.g., active-active configurations), optimizing service calls for proximity is crucial. This typically means a service instance should prioritize calling another service instance within its own local zone or data center. Only if local instances are unavailable should it attempt to reach instances in a remote zone. This article demonstrates how to achieve such proximity-aware load balancing using OpenFeign, Spring Cloud LoadBalancer, and Nacos.
Spring Cloud LoadBalancer: Zone Preference Strategy
Mechanism Overview
Spring Cloud LoadBalancer offers a built-in strategy for zone preference through its ZonePreferenceServiceInstanceListSupplier. This component intercepts the list of all available service instances and filters them based on a configured 'zone' preference. When a service consumer attempts to call a remote service, the ZonePreferenceServiceInstanceListSupplier first checks its own configured zone against the metadata of all discovered service instances. If any instances are found with matching 'zone' metadata, only those instance are returned for load balancing. If no instances in the preferred zone are available, it gracefully falls back to considering all available instances across all zones.
Configuration Example
To implement this, both the service provider and consumer need to specify their respective zones. The zone is typically defined as metadata during service registration and as a configuration property for the consuming service.
Service Provider Configuraton
The service providing endpoint registers itself with Nacos, including its zone information in the metadata:
spring:
application:
name: payment-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev-env
metadata:
# Assigns this service instance to 'datacenter-east'
zone: datacenter-east
Service Consumer Configuration
The service consuming payment-service specifies its preferred zone and enables the zone-preference load balancing configuration:
spring:
application:
name: order-processing-service
cloud:
loadbalancer:
# Activates the zone-preference strategy
configurations: zone-preference
# Specifies the consumer's preferred zone
zone: datacenter-east
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev-env
metadata:
# It's good practice for the consumer to also declare its zone
zone: datacenter-east
Nacos-based Load Balancing: Cluster Preference Strategy
Mechanism Overview
Nacos itself provides a load balancing mechanism that can prioritize instances within the same logical Nacos cluster. The NacosLoadBalancer component, integrated with Spring Cloud LoadBalancer, operates by examining the 'nacos.cluster' metadata of registered service instances. It compares this cluster name with the spring.cloud.nacos.discovery.cluster-name configured for the service consumer. If instances belonging to the consumer's specified cluster are available, the load balancer will exclusively route requests to them. In scenarios where no instances are found within the preferred cluster, it will then broaden its selection to include instances from other clusters.
Configuration Example
For this strategy, both service providers and consumers declare thier Nacos cluster names.
Service Provider Configuration
The service provider registers with Nacos, specifying its cluster affiliation:
spring:
application:
name: product-service
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev-env
# Assigns this service instance to 'europe-west' cluster
cluster-name: europe-west
Service Consumer Configuration
The service consumer configures itself to use Nacos's load balancing capabilities and declares its own cluster name:
spring:
application:
name: shopping-cart-service
cloud:
loadbalancer:
# Explicitly enables Nacos-specific load balancer behavior
nacos:
enabled: true
nacos:
discovery:
server-addr: 127.0.0.1:8848
namespace: dev-env
# Specifies the consumer's preferred cluster
cluster-name: europe-west