Use Spring Cloud to develop microservice applications and deploy them to SAE

Updated at:
Copy as MD

This tutorial walks you through building two Spring Cloud microservices — a service provider and a service consumer — from scratch, testing them locally with Nacos service registration and discovery, then deploying both to Serverless App Engine (SAE).

By the end, the consumer will discover and call the provider through Nacos, running on SAE in production.

The complete source code is available on GitHub.

Who this tutorial is for

Find your starting point and begin from there:

Your situationWhere to start
New to Spring CloudFollow every step. You will learn how Spring Cloud Alibaba Nacos Discovery implements service registration and discovery, and how to enable consumer-to-provider calls.
Familiar with Eureka, Consul, or ZooKeeperReplace your existing service registry dependencies and configuration with Spring Cloud Alibaba Nacos Discovery. No code changes are required — Spring Cloud Alibaba implements the standard Spring Cloud Registry interfaces.
Already using open-source Spring Cloud Alibaba Nacos DiscoverySkip to Step 4: Deploy to SAE.
If you want to skip local Nacos setup entirely, go directly to Step 4: Deploy to SAE and use the SAE built-in registry. No local Nacos Server is required in that path.

Prerequisites

Before you begin, ensure that you have:

  • Maven installed and added to your PATH

  • A running Nacos Server (required for Steps 1–3; not required if you skip to Step 4)

To start a local Nacos Server:

  1. Download and extract the Nacos Server package.

  2. Start Nacos in standalone mode:

    • Linux, Unix, or macOS: sudo sh startup.sh -m standalone

    • Windows: startup.cmd -m standalone

The -m standalone flag starts Nacos in standalone mode instead of cluster mode. On Windows, double-clicking startup.cmd starts it in cluster mode by default, which fails without a cluster configuration. If you see a startup error, open startup.cmd in a text editor, set MODE="standalone", and run the file again. For more details, see Quick Start for Nacos.

Choose a service registry

SAE supports three service registry options, listed from most to least recommended:

OptionBest forNotes
Microservices Engine (MSE) (recommended)Production workloads with many microservicesFully managed commercial Nacos; see Use an MSE Nacos registry
Self-managed registryTeams that need full controlRequires network connectivity between SAE and your Nacos cluster; see Self-managed registry notes below
SAE built-in registryGetting started or simple workloadsZero configuration; SAE auto-injects the Nacos Server address, port, namespace, AccessKey, and Context-path at deployment time
ZF182Dl2pw

SAE built-in registry

SAE provides automatic Nacos Server addressing for Java microservice applications. Configure it through the service registration and discovery feature in the SAE console. For setup instructions, see Use the SAE built-in Nacos registry.

x6JeUmPTQf

Self-managed registry notes

7D79jXUfBL

When using a self-managed Nacos registry with SAE, deploy your application as an image or JAR package and add these startup parameters before -jar:

-Dnacos.use.endpoint.parsing.rule=false -Dnacos.use.cloud.namespace.parsing=false
Important

Do not mix -D and -XX JVM parameters in the same argument — this causes the command to fail. Incorrect: Correct:

java -Dalicloud.deployment.mode=EDAS_MANAGED -XX:+UseContainerSupport -XX:InitialRAMPercentage=70.0 ... -jar /home/admin/app/xx-server.jar
java -XX:+UseContainerSupport -XX:InitialRAMPercentage=70.0 ... -Dnacos.use.endpoint.parsing.rule=false -Dnacos.use.cloud.namespace.parsing=false -jar /home/admin/app/xx-server.jar

For image deployments: Add the parameters to the image startup command:

RUN echo 'eval exec java -Dnacos.use.endpoint.parsing.rule=false -Dnacos.use.cloud.namespace.parsing=false -jar $CATALINA_OPTS /home/admin/app/hello-edas-0.0.1-SNAPSHOT.jar'> /home/admin/start.sh && chmod +x /home/admin/start.sh

For guidance on creating a Docker image, see Example of image creation.

For JAR package deployments: In the SAE console, go to Startup Command Settings and enter the parameters in the options Settings field.

sc_configure_a_startup_command_for_nacos

For more details, see Configure a startup command.

Step 1: Create the service provider

The service provider registers with Nacos and exposes an echo endpoint. This example uses Spring Boot 2.1.4.RELEASE and Spring Cloud Greenwich.SR1.

Spring Boot 2.4 and later are not supported. If you use Spring Cloud Alibaba 2.2.6.RELEASE, the required client version is 1.4.2.
  1. Create a Maven project named nacos-service-provider.

  2. Add the following to pom.xml:

    Spring Cloud Edgware has reached end of life. Use Greenwich or later for new projects.
    Spring Cloud versionSpring Cloud Alibaba version
    Greenwich (used in this example)2.1.1.RELEASE
    Finchley2.0.1.RELEASE
    Edgware (end of life)1.5.1.RELEASE
    <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.0.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>

    Version compatibility: Match your Spring Cloud version to the correct Spring Cloud Alibaba release:

  3. In src/main/java, create the package com.aliware.edas.

  4. In com.aliware.edas, create the startup class ProviderApplication. The @EnableDiscoveryClient annotation activates service registration and discovery:

    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);
        }
    }
  5. In com.aliware.edas, create EchoController. It maps GET requests to /echo/{string} and 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;
        }
    }
  6. In src/main/resources, create application.properties and point it at the local Nacos Server:

    spring.application.name=service-provider
    server.port=18081
    spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

    If your Nacos Server runs on a different host, replace 127.0.0.1 with its IP address. For all available configuration options, see the Configuration reference.

  7. Verify the registration:

    1. Run the main method of ProviderApplication.

    2. Open http://127.0.0.1:8848/nacos in a browser. The default username and password are both nacos.

    3. In the left navigation pane, choose Service Management > Service List. service-provider should appear in the list. Click Details to confirm.

Step 2: Create the service consumer

The service consumer registers with Nacos and calls the provider using two mechanisms: RestTemplate (with client-side load balancing) and FeignClient (declarative HTTP).

  1. Create a Maven project named nacos-service-consumer.

  2. Add the following to pom.xml. The consumer adds spring-cloud-starter-openfeign on top of the provider's dependencies:

    <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.0.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>
  3. In src/main/java, create the package com.aliware.edas.

  4. In com.aliware.edas, create the EchoService interface. The @FeignClient annotation binds it to the service-provider service registered in Nacos:

    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);
    }
  5. In com.aliware.edas, create the startup class ConsumerApplication:

    • @EnableDiscoveryClient — registers the consumer with Nacos

    • @EnableFeignClients — activates FeignClient scanning

    • @LoadBalanced on the RestTemplate bean — enables client-side load balancing through Nacos

    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);
        }
    }
  6. In com.aliware.edas, create TestController to expose two endpoints — one for each calling method:

    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 via RestTemplate with load balancing
        @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 via FeignClient
        @RequestMapping(value = "/echo-feign/{str}", method = RequestMethod.GET)
        public String feign(@PathVariable String str) {
            return echoService.echo(str);
        }
    }
  7. In src/main/resources, create application.properties:

    spring.application.name=service-consumer
    server.port=18082
    spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
  8. Verify the registration:

    1. Run the main method of ConsumerApplication.

    2. Open http://127.0.0.1:8848/nacos (username and password: nacos).

    3. Choose Service Management > Service List. Confirm that service-consumer appears in the list.

Step 3: Test locally

With both services running, send test requests from the consumer to the provider.

Linux, Unix, or macOS:

curl http://127.0.0.1:18082/echo-rest/rest-rest
curl http://127.0.0.1:18082/echo-feign/feign-rest

Windows: Enter the following URLs in a browser:

http://127.0.0.1:18082/echo-rest/rest-rest
http://127.0.0.1:18082/echo-feign/feign-rest

Both endpoints return the path parameter as the response body, confirming that the consumer discovered and called the provider successfully.

Step 4: Deploy to SAE

Deploy nacos-service-provider and nacos-service-consumer as two separate applications. Both must be in the same region and namespace for service discovery to work.

For step-by-step deployment instructions, see Deploy a Java application.

Set the Application runtime environment based on your package type:

Package typeApplication runtime environment
JAR packageStandard Java Application Runtime Environment
WAR packageapache-tomcat-XXX

When the application starts on SAE, the built-in service registry automatically injects the Nacos Server address, service port, namespace, AccessKey, and Context-path. These values take precedence over any settings in application.properties. Your original configuration can stay in place or be removed — either works.

Step 5: Verify the deployment

  1. Bind a public-facing Classic Load Balancer (CLB) to the nacos-service-consumer application. When configuring public access, set Network Protocol to HTTP, HTTP Port to 80, and Container Port to 18082. For details, see Bind a CLB to an application.

  2. In a browser, enter the CLB's public IP address in one of these formats:

    http://<public-IP-address>/echo-rest/rest-rest
    http://<public-IP-address>/echo-feign/feign-rest

    A response returned on the page confirms the deployment is working.

Configuration reference

Spring Cloud Alibaba Nacos Discovery configuration properties for application.properties:

KeyDefaultDescription
spring.cloud.nacos.discovery.server-addrNoneIP address and port of Nacos Server
spring.cloud.nacos.discovery.service${spring.application.name}Name under which the service registers
spring.cloud.nacos.discovery.network-interfaceNoneNetwork interface to use for registration; falls back to the first available interface if not set
spring.cloud.nacos.discovery.ipNoneExplicit IP address to register (takes precedence over interface detection)
spring.cloud.nacos.discovery.port-1Port to register; auto-detected if not specified
spring.cloud.nacos.discovery.namespaceNoneNamespace for environment isolation (for example, separating development from production)
spring.cloud.nacos.discovery.metadataNoneCustom metadata in map format
spring.cloud.nacos.discovery.cluster-nameDEFAULTNacos cluster name
spring.cloud.nacos.discovery.endpointNoneDomain name for dynamic Nacos Server address resolution; not required when deploying to SAE
ribbon.nacos.enabledtrueEnables Ribbon integration with Nacos; do not change unless required

For the full list of configuration options, see Nacos Discovery.

What's next