When multiple instances of a service run behind a single service name, the consumer needs a way to distribute requests across them. Spring Cloud applications on Enterprise Distributed Application Service (EDAS) use Ribbon for client-side load balancing. Ribbon intercepts service calls made through RestTemplate and Feign, then distributes requests across instances registered in Nacos.
How it works
Nacos acts as the service registry. When a service consumer calls a provider by name (for example, http://service-provider/query), Ribbon resolves the name to a list of registered instances and distributes requests across them.
Nacos implements the standard com.netflix.loadbalancer.ServerList interface through NacosServerList. Other service discovery tools implement the same interface:
| Service discovery tool | ServerList implementation |
|---|---|
| Nacos | NacosServerList |
| Eureka | DomainExtractingServerList |
| Consul | ConsulServerList |
| ZooKeeper | ZookeeperServerList |
Because all implementations share this interface, switching from Eureka, Consul, or ZooKeeper to Spring Cloud Alibaba requires no changes to your RestTemplate, Feign, or deprecated AsyncRestTemplate code.
Prerequisites
Before you begin, make sure that you have:
A Spring Cloud application deployed on EDAS with Nacos as the service registry
At least one service provider and one service consumer
(Optional) The Hystrix dependency added to your consumer to ensure compatibility between EDAS and Hystrix. It supports the fallback attribute. This can also be implemented by Sentinel
Sample applications
Download the demo projects to follow along:
Add load balancing to RestTemplate
RestTemplate is a Spring HTTP client for RESTful services. Add the @LoadBalanced annotation to a RestTemplate bean to enable client-side load balancing.
public class MyApp {
// The @LoadBalanced annotation adds LoadBalancerInterceptor to this RestTemplate.
// LoadBalancerInterceptor uses RibbonLoadBalancerClient to distribute requests
// across service instances registered in Nacos.
@Autowired
private RestTemplate restTemplate;
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
// Use the service name ("service-provider") instead of a hostname.
// Ribbon resolves it to an available instance.
public void doSomething() {
Foo foo = restTemplate.getForObject("http://service-provider/query", Foo.class);
doWithFoo(foo);
}
...
}@LoadBalancedon the@Beanmethod registers aLoadBalancerInterceptorthat routes requests throughRibbonLoadBalancerClient.Use the service name (for example,
service-provider) as the hostname in the URL. Ribbon replaces it with the IP address and port of an available instance.
Add load balancing to Feign
Feign is a declarative HTTP client that simplifies RESTful API calls. Load balancing works automatically when a Feign client references a service name registered in Nacos.
Step 1: Enable Feign
Add
@EnableFeignClientsto your Spring Boot application class:@SpringBootApplication @EnableFeignClients public class MyApplication { ... }Step 2: Define a Feign client interface
Create an interface annotated with
@FeignClient. Set thenameparameter to the target service name:@FeignClient(name = "service-provider") public interface EchoService { @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET) String echo(@PathVariable("str") String str); }Step 3: Inject and call the Feign client
Inject the interface and call its methods. Each call triggers an HTTP request to one of the
service-providerinstances:public class MyService { @Autowired private EchoService echoService; public void doSomething() { // Equivalent to GET http://service-provider/echo/test // Ribbon selects an instance from Nacos and routes the request. echoService.echo("test"); } ... }
Verify load balancing
After the service-consumer service and multiple service-provider services are started, access the URL that is provided by service-consumer to check whether load balancing is implemented.
RestTemplate
Access
/echo-rest/rest-testmultiple times and check whether the requests are forwarded to different instances.Feign
Access
/echo-feign/feign-testmultiple times and check whether the requests are forwarded to different instances.