SpringCloud Alibaba - Nacos registry

Posted by blaster_master on Sat, 19 Feb 2022 11:25:14 +0100

Parent project
Create a maven project l-cloud-alibaba, delete the src directory and modify POM The XML content is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<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>
      	<!-- Common 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 version-->
        <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 version-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>

</project>

In order to facilitate me to put some public dependencies and code, we create a cloud common module, POM The XML content is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<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>Common 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>

Then on COM codelong. Create a result. Under the base package Java and codeandmsg Java represents 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;

/**
 * Responder encapsulation
 *
 * @param <T>
 * @author codelong
 * @since 1.0
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
@Slf4j
@Data
public class Result<T> implements Serializable {

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

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

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

    private Result(int status, String message, boolean success) {
        this();
        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();
        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;
    }

    /**
     * Create a successful 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);
    }

    /**
     * Create failed 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);
    }

}

CodeAndMsg.java

/**
 * Status code set
 *
 * @author codelong
 * @since 1.0
 */
public enum CodeAndMsg {
    /**
     * Operation successful
     **/
    RC100(100, "Request succeeded"),
    /**
     * operation failed
     **/
    RC999(999, "operation failed"),
    /**
     * Service current limiting
     **/
    RC200(200, "Service open current limiting protection,Please try again later!"),
    /**
     * service degradation 
     **/
    RC201(201, "Service enable degradation protection,Please try again later!"),
    /**
     * Hot spot parameter current limiting
     **/
    RC202(202, "Hot spot parameter current limiting,Please try again later!"),
    /**
     * System rules are not met
     **/
    RC203(203, "System rules do not meet requirements,Please try again later!"),
    /**
     * Authorization rule failed
     **/
    RC204(204, "Authorization rule failed,Please try again later!"),
    /**
     * access_denied
     **/
    RC403(403, "Exception when anonymous users access resources without permission"),
    /**
     * access_denied
     **/
    RC401(401, "Exception 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() {
        return code;
    }

    public String getMessage() {
        return message;
    }
}

Create microservices
Here, we use cloud Nacos register and cloud Nacos consumer to simulate the invocation between microservices.

Create cloud Nacos register micro service
Create a sub module cloud Nacos register under the parent module.

pom. The XML content is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<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>

Then create a RegisterController class under the controller package and provide an interface for consumers to call. The contents of RegisterController are as follows:

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);
    }

}

Modify application YML file, as follows:

server:
  port: 8001  # Service port number
spring:
  application:
    name: provider-service  # Service name, which is also the micro service ID registered in the micro service by default
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848  # Specify the address of the Nacos registry
      username: nacos # The user name of the nacos server. The default is nacos
      password: nacos # The password of the nacos server. The default is nacos

Create cloud Nacos consumer micro service
Create a sub module cloud Nacos consumer under the parent module.

pom. The XML content is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<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>

Then create a RegisterController class under the controller package and provide an interface for consumers to call. The contents of RegisterController are as follows:

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);
    }

}

Modify application YML file, as follows:

server:
  port: 8001  # Service port number
spring:
  application:
    name: provider-service  # Service name, which is also the micro service ID registered in the micro service by default
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848  # Specify the address of the Nacos registry
      username: nacos # The user name of the nacos server. The default is nacos
      password: nacos # The password of the nacos server. The default is nacos

Create cloud Nacos consumer micro service
Create a sub module cloud Nacos consumer under the parent module.

pom. The XML content is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<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>Serving consumers</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>

Then create a ConsumerController class under the controller package and provide an interface to call the above services. The contents of ConsumerController are as follows:

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 point: replace the original IP: port with the service name, and RestTemplate will automatically use the Ribbon to query the list of available provider service instances before communication
        // Then select the node instance according to the load balancing strategy
        return restTemplate.getForObject(String.format("http://provider-service/provider/%s", message), String.class);
    }
}

Then create a ConsumerConfigure configuration class under the configure package, inject RestTemplate and add @ 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 // Enables RestTemplate objects to automatically support Ribbon load balancing
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

Modify application YML file, as follows:

server:
  port: 9001  # Service port number
spring:
  application:
    name: consumer-service  # Service name, which is also the micro service ID registered in the micro service by default
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848  # Specify the address of the Nacos registry
      username: nacos # The user name of the nacos server. The default is nacos
      password: nacos # The password of the nacos server. The default is nacos

logging:
  level:
    root: debug # For the convenience of reading the log, it is only opened during development, not officially

Setting logging to debug level here is to make it easy to see the log 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 in to the Nacos console to view the list of services:

You can see that both services are registered. Then visit the browser: http://localhost:9001/consumer/nacos :

If the call is successful, the service discovery is successful.

Test load balancing
As shown in the figure below, right-click ProviderApplication and select Copy Configuration

Then fill in the relevant contents as shown in the figure below:

Then start the service you just copied

Log in to the Nacos console and check the service list. It is found that there are two instances of the provider

Then visit many times: http://localhost:9001/consumer/nacos , you can see that the requests are balanced (the default is polling algorithm):

Nacos registry configuration

Configuration itemKeyDefault valueexplain
Server addressspring.cloud.nacos.discovery.server-addrThe IP and port of the Nacos server listener
Service namespring.cloud.nacos.discovery.service${spring.application.name}Current service name
Service groupingspring.cloud.nacos.discovery.groupSet the group in which the service is located
weightspring.cloud.nacos.discovery.weight1Value range: 1 to 100. The higher the value, the greater the weight
adapter namespring.cloud.nacos.discovery.network-interfaceIf no IP address is specified, the registered IP address is the IP address of the network card. If it is not specified, the IP address of the first network card will be used by default.
Registered IP addressspring.cloud.nacos.discovery.ipHighest priority
Registered portspring.cloud.nacos.discovery.port-1By default, it is not configured and will be detected automatically
Namespacespring.cloud.nacos.discovery.namespaceOne of the common scenarios is the separation and isolation of registrations in different environments, such as the isolation of resources (such as configuration and service) between development and test environments and production environments.
AccessKeyspring.cloud.nacos.discovery.access-keyWhen going to alicloud, a cloud account name on alicloud
SecretKeyspring.cloud.nacos.discovery.secret-keyWhen you want to go to alicloud, you need a cloud account password on alicloud
Metadataspring.cloud.nacos.discovery.metadataUsing Map format configuration, users can customize some metadata information related to services according to their own needs
Log file namespring.cloud.nacos.discovery.log-name
Cluster namespring.cloud.nacos.discovery.cluster-nameDEFAULTConfigured as Nacos cluster name
Access pointspring.cloud.nacos.discovery.endpointThe entry domain name of a service in the region. Through this domain name, you can dynamically get the server address
Is Ribbon integratedribbon.nacos.enabledtrueGenerally, it can be set to true
Enable the Nacos Watchspring.cloud.nacos.discovery.watch.enabledtrueYou can set it to false to turn off the watch

At the end of the article, the author sorted out a lot of materials for you! Including Java core knowledge points + a full set of architect learning materials and videos + first-line large factory interview classic + interview resume template + java architecture practical e-book and so on!
All free to share with you, if you need friends Just download it here , verification code: csdn

Topics: Java