SpringCloud Alibaba – Nacos注册中心

父项目

创建一个maven项目l-cloud-alibaba,将src目录删除,修改pom.xml内容如下:

<?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>
      	<!-- 公共模块-->
        <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>

        <!-- 第三方依赖版本-->
        <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>

            <!-- 第三方依赖版本-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <version>${lombok.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>

</project>
复制代码

为了方便我放一些公共的依赖和代码,我们创建一个cloud-common模块,pom.xml内容如下:

<?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>公共模块</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>
复制代码

然后在com.codelong.base包下分别创建Result.javaCodeAndMsg.java 分别代表统一响应内容封装状态码封装

Result.java

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

import java.io.Serializable;

/**
 * 响应体封装
 *
 * @param <T>
 * @author codelong
 * @since 1.0
 */
@JsonInclude(JsonInclude.Include.NON_NULL)
@Slf4j
@Data
public class Result<T> implements Serializable {

    /**
     * 状态码
     */
    private int status;
    /**
     * 消息
     */
    private String message;

    /**
     * 数据
     */
    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;
    }

    /**
     * 创建成功的响应
     */
    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);
    }

    /**
     * 创建失败的响应
     */
    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

/**
 * 状态码集合
 *
 * @author codelong
 * @since 1.0
 */
public enum CodeAndMsg {
    /**
     * 操作成功
     **/
    RC100(100, "请求成功"),
    /**
     * 操作失败
     **/
    RC999(999, "操作失败"),
    /**
     * 服务限流
     **/
    RC200(200, "服务开启限流保护,请稍后再试!"),
    /**
     * 服务降级
     **/
    RC201(201, "服务开启降级保护,请稍后再试!"),
    /**
     * 热点参数限流
     **/
    RC202(202, "热点参数限流,请稍后再试!"),
    /**
     * 系统规则不满足
     **/
    RC203(203, "系统规则不满足要求,请稍后再试!"),
    /**
     * 授权规则不通过
     **/
    RC204(204, "授权规则不通过,请稍后再试!"),
    /**
     * access_denied
     **/
    RC403(403, "匿名用户访问无权限资源时的异常"),
    /**
     * access_denied
     **/
    RC401(401, "认证用户访问无权限资源时的异常");

    /**
     * 自定义状态码
     **/
    private final int code;
    /**
     * 自定义描述
     **/
    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;
    }
}
复制代码

创建微服务

我们这里使用提供者(cloud-nacos-register)和消费者(cloud-nacos-consumer)来模拟微服务之间的调用。

创建cloud-nacos-register微服务

在父模块下创建一个子模块cloud-nacos-register。

pom.xml内容如下:

<?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>服务提供者</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>
复制代码

然后在controller包下创建一个RegisterController类,提供一个接口给消费者调用,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);
    }

}
复制代码

修改application.yml文件,内容如下:

server:
  port: 8001  # 服务端口号
spring:
  application:
    name: provider-service  # 服务名称,默认也是在微服务中注册的微服务ID
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848  # 指定Nacos注册中心的地址
      username: nacos # Nacos服务器的用户名,默认为 nacos
      password: nacos # Nacos服务器的密码,默认为 nacos
复制代码

创建cloud-nacos-consumer微服务

在父模块下创建一个子模块cloud-nacos-consumer。

pom.xml内容如下:

<?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>服务消费者</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>
复制代码

然后在controller包下创建一个ConsumerController类,提供一个接口调用上面的服务,ConsumerController内容如下:

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) {
        // 关键点:将原有IP:端口替换为服务名,RestTemplate便会在通信前自动利用Ribbon查询可用provider-service实例列表
        // 再根据负载均衡策略选择节点实例
        return restTemplate.getForObject(String.format("http://provider-service/provider/%s", message), String.class);
    }
}
复制代码

然后在configure包下创建一个ConsumerConfigure配置类,注入RestTemplate并加上@LoadBalanced注解来支持Ribbon负载均衡:

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 // 使RestTemplate对象自动支持Ribbon负载均衡
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}
复制代码

修改application.yml文件,内容如下:

server:
  port: 9001  # 服务端口号
spring:
  application:
    name: consumer-service  # 服务名称,默认也是在微服务中注册的微服务ID
  cloud:
    nacos:
      server-addr: 127.0.0.1:8848  # 指定Nacos注册中心的地址
      username: nacos # Nacos服务器的用户名,默认为 nacos
      password: nacos # Nacos服务器的密码,默认为 nacos

logging:
  level:
    root: debug # 为了方便看日志,只在开发时开启,正式不要开
复制代码

这里将logging设置成debug级别是为了方便看到负载均衡调用的日志。

最终项目结构如下

image-20210420111512257

启动提供者和消费者

分别启动cloud-nacos-registercloud-nacos-consumer项目

image-20210420111638138

登录Nacos控制台查看服务列表:

image-20210420111712046

可以看到,两个服务都注册进来了。接着浏览器访问:http://localhost:9001/consumer/nacos:

image-20210420112027984

调用成功,说明服务发现成功。

测试负载均衡

如下图所示,在ProviderApplication上右键选择Copy Configuration…:

image-20210420112220673

然后按照下图所示填写相关内容:

image-20210420112417314

然后启动刚刚复制的服务

image-20210420112456300

登录Nacos控制台查看服务列表发现provider有2个实例

image-20210420112532627

然后多次访问:http://localhost:9001/consumer/nacos,可以看到请求是均衡的(默认为轮询算法):

img

Nacos注册中心配置

配置项 Key 默认值 说明
服务端地址 spring.cloud.nacos.discovery.server-addr Nacos服务器侦听器的IP和端口
Service name spring.cloud.nacos.discovery.service ${spring.application.name} 当前服务名称
服务分组 spring.cloud.nacos.discovery.group 设置服务所处的分组
权重 spring.cloud.nacos.discovery.weight 1 取值范围:1到100。值越大,权重越大
网卡名 spring.cloud.nacos.discovery.network-interface 如果未指定IP地址,则注册的IP地址是网卡的IP地址。如果也未指定,则默认情况下将使用第一张网卡的IP地址。
注册的IP地址 spring.cloud.nacos.discovery.ip 优先级最高
注册的端口 spring.cloud.nacos.discovery.port -1 默认情况下不用配置,会自动探测
命名空间 spring.cloud.nacos.discovery.namespace 常用场景之一是不同环境的注册的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
AccessKey spring.cloud.nacos.discovery.access-key 当要上阿里云时,阿里云上面的一个云账号名
SecretKey spring.cloud.nacos.discovery.secret-key 当要上阿里云时,阿里云上面的一个云账号密码
Metadata spring.cloud.nacos.discovery.metadata 使用Map格式配置,用户可以根据自己的需要自定义一些和服务相关的元数据信息
日志文件名 spring.cloud.nacos.discovery.log-name
集群名 spring.cloud.nacos.discovery.cluster-name DEFAULT 配置成Nacos集群名称
接入点 spring.cloud.nacos.discovery.endpoint 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
是否集成Ribbon ribbon.nacos.enabled true 一般都设置成true即可
是否开启Nacos Watch spring.cloud.nacos.discovery.watch.enabled true 可以设置成false来关闭 watch
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享