When multiple Spring Cloud microservices need to discover and call each other at runtime, a centralized service registry is required. Microservices Engine (MSE) provides a fully managed Nacos registry that handles service registration, service discovery, and configuration management -- so you can focus on application logic instead of operating registry infrastructure.
This tutorial walks you through building a provider and a consumer application, registering both with an MSE Nacos instance, and verifying end-to-end communication between them. The consumer demonstrates two service invocation approaches: RestTemplate and FeignClient.
MSE also supports ZooKeeper and Eureka as registry engines. This tutorial uses Nacos. If you use ZooKeeper or Eureka, replace the discovery dependency and configuration accordingly. For details, see Usage notes.
Prerequisites
Before you begin, make sure you have:
Maven installed and configured in your system PATH
An MSE Nacos instance -- see Create an instance
A namespace in your MSE instance -- see Create a namespace. This tutorial uses the default Public namespace
To access the MSE Nacos registry over the Internet, both the provider and consumer must have Internet connectivity. Configure a public IP address whitelist for the registry before proceeding. For details, see Configure a public IP address whitelist.
Version compatibility
This tutorial uses Spring Boot 2.1.4.RELEASE with Spring Cloud Greenwich.SR1. The following table lists the Spring Cloud Alibaba version for each supported Spring Cloud release.
| Spring Cloud version | Spring Cloud Alibaba version | Status |
|---|---|---|
| Greenwich | 2.1.1.RELEASE | Supported |
| Finchley | 2.0.1.RELEASE | Supported |
| Edgware | 1.5.1.RELEASE | Discontinued |
Spring Cloud Edgware has been discontinued. Do not use it for new applications.
Step 1: Build the provider
Create a Spring Cloud application that exposes a REST endpoint and registers as a service provider with MSE Nacos.
1.1 Create the Maven project
Create a Maven project named nacos-service-provider.
1.2 Add dependencies
Add the following to the pom.xml file:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>1.3 Create the boot class and controller
Under src/main/java, create the package com.aliware.edas.
In the com.aliware.edas package, create the boot class ProviderApplication. The @EnableDiscoveryClient annotation activates service registration and discovery with the configured Nacos server.
package com.aliware.edas;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
}
}In the same package, create a controller class named EchoController. This controller exposes a GET /echo/{string} endpoint that returns the path variable.
package com.aliware.edas;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class EchoController {
@RequestMapping(value = "/echo/{string}", method = RequestMethod.GET)
public String echo(@PathVariable String string) {
return string;
}
}1.4 Configure the Nacos server endpoint
Under src/main/resources, create application.properties with the following content:
spring.application.name=service-provider
server.port=18081
spring.cloud.nacos.discovery.server-addr=<your-nacos-endpoint>:8848Replace <your-nacos-endpoint> with your MSE Nacos public endpoint. Find this value on the Instances page of the MSE console. The endpoint follows the format mse.XX.nacos.mse.aliyuncs.com.
To use a custom namespace instead of the default Public namespace, add:
spring.cloud.nacos.discovery.namespace=<namespace-id>1.5 Verify provider registration
Run the
mainmethod of ProviderApplication in the nacos-service-provider project to start the provider.Log on to the MSE console.
Select a region in the top navigation bar.
In the left-side navigation pane, choose Microservices Registry > Instances, then click the instance name.
Choose Service Management > Services.
Confirm that
service-providerappears in the service list.
Step 2: Build the consumer
Create a Spring Cloud application that discovers and calls the provider through MSE Nacos. This consumer demonstrates two service invocation approaches: RestTemplate and FeignClient.
| Approach | Description | When to use |
|---|---|---|
| RestTemplate | Programmatic HTTP client with @LoadBalanced for service discovery | Simple HTTP calls where you want full control over the request |
| FeignClient | Declarative HTTP client that maps service interfaces to method calls | Complex service interfaces where you prefer annotation-driven code |
2.1 Create the Maven project
Create a Maven project named nacos-service-consumer.
2.2 Add dependencies
Add the following to the pom.xml file. Compared to the provider, the consumer adds spring-cloud-starter-openfeign for declarative HTTP client support.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>2.3 Create the Feign client interface
Under src/main/java, create the package com.aliware.edas.
In the com.aliware.edas package, create an interface named EchoService. The @FeignClient annotation declares this as a Feign client that targets the service-provider service by name. Nacos resolves the service name to an available instance automatically.
package com.aliware.edas;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
@FeignClient(name = "service-provider")
public interface EchoService {
@RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
String echo(@PathVariable("str") String str);
}2.4 Create the boot class
In the com.aliware.edas package, create the boot class ConsumerApplication with the following annotations:
| Annotation | Purpose |
|---|---|
@EnableDiscoveryClient | Activates service registration and discovery with Nacos |
@EnableFeignClients | Enables component scanning for @FeignClient interfaces |
@LoadBalanced (on RestTemplate bean) | Integrates RestTemplate with Nacos service discovery for client-side load balancing |
package com.aliware.edas;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class ConsumerApplication {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}2.5 Create the test controller
In the com.aliware.edas package, create a controller named TestController that exposes two endpoints -- one using RestTemplate and one using FeignClient -- to demonstrate both service discovery approaches.
package com.aliware.edas;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class TestController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private EchoService echoService;
// Calls the provider using RestTemplate with service discovery
@RequestMapping(value = "/echo-rest/{str}", method = RequestMethod.GET)
public String rest(@PathVariable String str) {
return restTemplate.getForObject("http://service-provider/echo/" + str,
String.class);
}
// Calls the provider using FeignClient
@RequestMapping(value = "/echo-feign/{str}", method = RequestMethod.GET)
public String feign(@PathVariable String str) {
return echoService.echo(str);
}
}2.6 Configure the Nacos server endpoint
Under src/main/resources, create application.properties with the following content:
spring.application.name=service-consumer
server.port=18082
spring.cloud.nacos.discovery.server-addr=<your-nacos-endpoint>:8848Replace <your-nacos-endpoint> with the same MSE Nacos public endpoint used for the provider.
To use a custom namespace, add:
spring.cloud.nacos.discovery.namespace=<namespace-id>2.7 Verify consumer registration
Run the
mainmethod of ConsumerApplication in the nacos-service-consumer project to start the consumer.Log on to the MSE console.
Select a region in the top navigation bar.
In the left-side navigation pane, choose Microservices Registry > Instances, then click the instance name.
Choose Service Management > Services.
Confirm that
service-consumerappears in the service list.
Step 3: Test service calls
With both applications running, test end-to-end communication from the consumer to the provider.
On Linux, UNIX, or macOS, run the following curl commands:
curl http://127.0.0.1:18082/echo-rest/rest-rest
curl http://127.0.0.1:18082/echo-feign/feign-restOn Windows, open a browser and navigate to http://127.0.0.1:18082/echo-rest/rest-rest and http://127.0.0.1:18082/echo-feign/feign-rest.
Expected output:
rest-rest
feign-restIf both calls return the expected strings, the provider and consumer are communicating through the MSE Nacos registry.
FAQ
Services do not appear in the MSE console after startup
This typically happens when the application runs in an on-premises environment and the MSE Nacos registry has not been configured to allow inbound connections from your network.
Configure a public IP address whitelist to grant access. By default, the whitelist is set to 127.0.0.1/32, which blocks all external connections. For instructions, see Configure a public IP address whitelist.