The parent project

Create a Maven project l-cloud-Alibaba, delete the SRC directory and modify pom.xml as follows:


      
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.codelong</groupId>
    <artifactId>l-cloud-alibaba</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>

    <modules>
      	<! -- Public module -->
        <module>cloud-common</module>
      
        <module>cloud-nacos-register</module>
        <module>cloud-nacos-consumer</module>
    </modules>

    <properties>
        <java.version>1.8</java.version>
        <encoding>UTF-8</encoding>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.7. RELEASE</spring-boot.version>
        <spring-cloud-alibaba.version>2.2.2. RELEASE</spring-cloud-alibaba.version>
        <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>

        <! -- Third-party dependent versions -->
        <lombok.version>1.18.20</lombok.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${spring-cloud-alibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <! -- Third-party dependent versions -->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>

</project>
Copy the code

To make it easier for me to include some common dependencies and code, we create a cloud-common module, pom.xml with the following contents:


      
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <artifactId>l-cloud-alibaba</artifactId>
        <groupId>com.codelong</groupId>
        <version>1.0.0</version>
    </parent>
    <packaging>jar</packaging>

    <artifactId>cloud-common</artifactId>
    <name>common</name>
    <description>Public module</description>
    <dependencies>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
        </dependency>

    </dependencies>

</project>
Copy the code

Result. Java and codeandmsG. Java are created under com.codelong.base package to represent unified response content encapsulation and status code encapsulation respectively

Result.java

import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;

/** * Response body encapsulation **@param <T>
 * @author codelong
 * @since1.0 * /
@JsonInclude(JsonInclude.Include.NON_NULL)
@Slf4j
@Data
public class Result<T> implements Serializable {

    /** * Status code */
    private int status;
    /** * message */
    private String message;

    /** * data */
    private T data;
    private boolean success;
    private long timestamp;

    public Result(a) {
        this.timestamp = System.currentTimeMillis();
    }

    private Result(int status, String message, boolean success) {
        this(a);this.status = status;
        this.message = message;
        this.success = success;
    }

    private Result(int status, String message, boolean success, T data) {
        this(status, message, success);
        this.data = data;
    }

    private Result(CodeAndMsg codeAndMsg, boolean success) {
        this(a);this.status = codeAndMsg.getCode();
        this.message = codeAndMsg.getMessage();
        this.success = success;
    }

    private Result(CodeAndMsg codeAndMsg, boolean success, T data) {
        this(codeAndMsg, success);
        this.data = data;
    }

    /** * Successfully created response */
    public static <T> Result<T> success(int status, String message) {
        return new Result<T>(status, message, true);
    }

    public static <T> Result<T> success(CodeAndMsg codeAndMsg) {
        return new Result<T>(codeAndMsg, true);
    }

    public static <T> Result<T> success(int status, String message, T data) {
        return new Result<T>(status, message, true, data);
    }

    public static <T> Result<T> success(CodeAndMsg codeAndMsg, T data) {
        return new Result<T>(codeAndMsg, true, data);
    }

    /** * Failed to create a response */
    public static <T> Result<T> fail(int status, String message) {
        return new Result<T>(status, message, false);
    }

    public static <T> Result<T> fail(CodeAndMsg codeAndMsg) {
        return new Result<T>(codeAndMsg, false); }}Copy the code

CodeAndMsg.java

/** * Status code set **@author codelong
 * @since1.0 * /
public enum CodeAndMsg {
    /** * The operation succeeded **/
    RC100(100."Request successful"),
    /** * Operation failed **/
    RC999(999."Operation failed"),
    /** * Service traffic restriction **/
    RC200(200."Traffic limiting protection is enabled for service, please try again later!"),
    /** * Service degraded **/
    RC201(201."Service degraded protection enabled, please try again later!"),
    /** * Hotspot parameter limit **/
    RC202(202."Hotspot parameter limit, please try again later!"),
    /** * System rules do not meet **/
    RC203(203."System rules do not meet requirements, please try again later!"),
    /** * The authorization rule does not pass **/
    RC204(204."Authorization rule failed, please try again later!"),
    /** * access_denied **/
    RC403(403."Exceptions when anonymous Users access unauthorized resources"),
    /** * access_denied **/
    RC401(401."An exception occurs when an authenticated user accesses an unauthorized resource.");

    /** * Custom status code **/
    private final int code;
    /** * Custom description **/
    private final String message;

    CodeAndMsg(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public int getCode(a) {
        return code;
    }

    public String getMessage(a) {
        returnmessage; }}Copy the code

Creating a microservice

We here use providers (Cloud-nacos-Register) and consumers (Cloud-nacos-Consumer) to simulate calls between microservices.

Create the Cloud-nacos-Register microservice

Create a child module cloud-nacos-Register under the parent module.

The pom.xml content is as follows:


      
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>l-cloud-alibaba</artifactId>
        <groupId>com.codelong</groupId>
        <version>1.0.0</version>
    </parent>

    <artifactId>cloud-nacos-register</artifactId>
    <name>register-service</name>
    <description>Service provider</description>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
Copy the code

Then create a RegisterController class under the Controller package to provide an interface for the consumer to call RegisterController.

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("provider")
public class RegisterController {

    @Value("${server.port}")
    String port;

    @GetMapping("{message}")
    public String hello(@PathVariable String message) {
        return String.format("%s from %s", message, port); }}Copy the code

Modify the application.yml file as follows:

server:
  port: 8001  # Service port number
spring:
  application:
    name: provider-service  By default, this is also the microservice ID registered in the microservice
  cloud:
    nacos:
      server-addr: 127.0. 01.: 8848  Specify the address of the Nacos registry
      username: nacos The default user name of the server is Nacos
      password: nacos The default password of the server is Nacos
Copy the code

Create the Cloud-nacos-Consumer microservice

Create a child module cloud-nacos-Consumer under the parent module.

The pom.xml content is as follows:


      
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>l-cloud-alibaba</artifactId>
        <groupId>com.codelong</groupId>
        <version>1.0.0</version>
    </parent>

    <artifactId>cloud-nacos-consumer</artifactId>
    <name>consumer-service</name>
    <description>Service consumer</description>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
Copy the code

Then create a ConsumerController class under the Controller package that provides an interface to invoke the above service. ConsumerController says the following:

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;

@RestController
@RequestMapping("consumer")
public class ConsumerController {

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/{message}")
    public String hello(@PathVariable String message) {
        // Key points: Replace the original IP address: port with the service name, and the RestTemplate will automatically use the Ribbon to query the list of available provider-service instances before communication
        // Select node instances based on the load balancing policy
        return restTemplate.getForObject(String.format("http://provider-service/provider/%s", message), String.class); }}Copy the code

Then create a ConsumerConfigure configuration class in the Configure package, inject the RestTemplate and add the @loadBalanced annotation to support Ribbon load balancing:

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class ConsumerConfigure {

    @Bean
    @LoadBalanced // Make the RestTemplate object automatically support Ribbon load balancing
    public RestTemplate restTemplate(a) {
        return newRestTemplate(); }}Copy the code

Modify the application.yml file as follows:

server:
  port: 9001  # Service port number
spring:
  application:
    name: consumer-service  By default, this is also the microservice ID registered in the microservice
  cloud:
    nacos:
      server-addr: 127.0. 01.: 8848  Specify the address of the Nacos registry
      username: nacos The default user name of the server is Nacos
      password: nacos The default password of the server is Nacos

logging:
  level:
    root: debug # For ease of viewing logs, only enable it during development, not officially
Copy the code

The logging is set to Debug to make it easier to see logs of load balancing calls.

The final project structure is as follows

Start providers and consumers

Start the Cloud-NACos-Register and Cloud-Nacos-Consumer projects respectively

Log on to the Nacos Console for a list of services:

As you can see, both services are registered. Then the browser visit: http://localhost:9001/consumer/nacos:

If the invocation succeeds, the service is successfully discovered.

Test load balancing

As shown below, right-click on ProviderApplication and select Copy Configuration… :

Then fill in the relevant content as shown below:

Then start the service you just copied

Log in to the Nacos console to view the list of services and discover that the Provider has two instances

Then repeatedly visit: http://localhost:9001/consumer/nacos, you can see the request is balanced (the default is polling algorithm) :

Nacos registry configuration

Configuration items Key The default value instructions
Server address spring.cloud.nacos.discovery.server-addr IP and port of the Nacos server listener
Service name spring.cloud.nacos.discovery.service ${spring.application.name} Current Service name
Service group spring.cloud.nacos.discovery.group Sets the group to which the service belongs
The weight spring.cloud.nacos.discovery.weight 1 Value range: 1 to 100. The greater the value, the greater the weight
The network card name spring.cloud.nacos.discovery.network-interface If no IP address is specified, the registered IP address is the IP address of the nic. If this parameter is not specified, the IP address of the first nic is used by default.
Registered IP address spring.cloud.nacos.discovery.ip Highest priority
Registered port spring.cloud.nacos.discovery.port - 1 By default, no configuration is required and automatic detection is performed
The namespace spring.cloud.nacos.discovery.namespace One common scenario is the separation of registration between different environments, such as isolation of resources (such as configurations and services) between development test environments and production environments.
AccessKey spring.cloud.nacos.discovery.access-key When you want to go to Ali Cloud, ali cloud above a cloud account name
SecretKey spring.cloud.nacos.discovery.secret-key When you want to go on Ali cloud, ali cloud above a cloud account password
Metadata spring.cloud.nacos.discovery.metadata Using the Map format, users can customize metadata related to services as required
Log file name spring.cloud.nacos.discovery.log-name
The cluster name spring.cloud.nacos.discovery.cluster-name DEFAULT Configure to Nacos cluster name
Access point spring.cloud.nacos.discovery.endpoint An inbound domain name of a service in a region through which you can dynamically obtain the server address
Whether to integrate Ribbon ribbon.nacos.enabled true It is usually set to true
Whether to enable Nacos Watch spring.cloud.nacos.discovery.watch.enabled true You can set it to false to turn off watch