微服务 - Nacos

Nacos 认识和安装

Nacos 是阿里巴巴的产品,现在是SpringCloud中的一个组件。相比Eureka 功能更加丰富,在国内受欢迎程度较高

官网:nacos.io

# 启动
.\startup.cmd -m standalone

启动成功后访问:http://192.168.222.1:8848/nacos/index.html

默认的账号密码:nacos/nacos

服务注册

1.父工程 cloud-demo 的POM 中引入依赖:

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-dependencies</artifactId>
    <version>2.2.5.RELEASE</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

2.user-service 和 order-service 中分别引入 nacos 依赖:

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

3.服务中配置服务名称和nacos 服务地址:

以user-service 为列:

spring:
  application:
    name: userservice # 注册到nacos 的服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # naocs 服务地址

Nacos 服务分级存储模型

服务跨集群调用问题:
服务调用尽可能选择本地集群服务,跨集群调用延迟较高
当本地集群不可访问时,再去访问其他集群

集群配置:

spring:
  application:
    name: userservice #服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # naocs 服务地址
      discovery:
        cluster-name: GZ # 集群名称

启动3个user-service 实例 来模拟两个集群:
user-service 配置集群为 SZ
user-service2 配置集群为 SZ
user-service3 配置集群为 GZ

NacosRule 负载均衡

需求:order-servce 优先使用同集群的服务,同集群的服务不可用时才调用其他集群的服务

  1. order-service 配置集群为 SZ 与 user-service 及 user-service2同 以个集群

  2. 更改 user-servic的负载均衡策略

userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则

访问order-service 4次:

可以看到 请求user-service 都访问到了user-service 及user-service2,而没有请求到另一个集群的user-service3

如果将user-service 及user-service2 停掉后保留user-service3服务,再次访问order-service:

请求都打到user-service3 上:

并且order-service 会有以下警告日志

Nacos 服务实例的权重设置

实际部署中会出现这样的场景:

服务设备性能有差异,部分实例所在机器性能较好,另外一些较差,我们希望性能好的机器承担更多的用户请求
Nacos 提供了权重配置来控制访问频率,权重越大则访问频率越高

实验1:user-service2 的权重修改为0.1
结果: 请求10次,2次打在user-service2,8次打在user-service

实验2:user-service2 的权重修改为0
结果: 请求10次,全部打在user-service

总结:
实例的权重控制:

  • Nacos 控制台可以设置实例的权重值,0-1之间
  • 同集群内的多个实例,权重越高被访问的频率越高
  • 权重设置为0则完全不会被访问

Nacos 环境隔离

Nacos 服务存储和数据存储的最外层都是一个名为namespace的东西,用来做最外层隔离

  • namespace 用来做环境隔离
  • 每个namespace 都有唯一id
  • 不同namespace 下的服务不可见

新建一个namespace:
1.

新建完毕后在服务列表就可以看到namespace:

新建完毕后将orderf-service 放入到dev 空间:

spring:
  application:
    name: orderserivce # eureka 的服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos 服务地址
      discovery:
        cluster-name: SZ  # 集群名称e
        namespace: ee9e5ae9-4cba-4681-8107-efddf0597abe # namespace id

此时order-service 就不能在使用 user-service的服务,因为两者在不同的命名空间中,请求会报错:

Nacos 和 Eureka 的区别

共同点:

  • 都支持服务注册和拉取
  • 都支持服务者心跳方法做健康检测

区别:

  • Nacos 支持服务端主动检测提供者装状态:临时实例采用心跳模式,非临时实例采用主动检测模式
  • 临时实例心跳不正常会被剔除,非临时实例则不会被剔除(推荐使用临时实例,非临时实例需要主动询问,服务器压力大)
  • Nacos 支持服务列表变更的消息推送模式,服务列表更新及时
  • Nacos集群默认采用AP方式,当集群中存在非临时实例时,采用CP模式;Eureka采用AP方式

案例:默认服务为临时实例,将临时实例修改为非临时实例

1.关闭order-service 后服务被剔除:

2.修改application.yml

spring:
  application:
    name: orderserivce # eureka 的服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos 服务地址
      discovery:
        cluster-name: SZ  # 集群名称e
        namespace: ee9e5ae9-4cba-4681-8107-efddf0597abe # namespace id
        ephemeral: false # 非临时实例

3.关闭order-service 后,服务不会被剔除:

Nacos 配置管理

Nacos 配置管理 可以实现配置热更新,将一些经常发发生变更的配置放入到Nacoos 配置管理中,不用重启服务就可以生效

最终的配置就等于: Nacos 配置 + 微服务中的application.yaml 中的配置

新建配置文件:
在这里加入一个配置作为测试使用:

新建成功

Nacos 配置拉取

SpringBoot 项目启动时读取配置文件的顺序:

热更新方式一

拉取步骤如下:
1.user-service 引入Nacos 引入配置管理依赖

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

2.新建bootstrap.yml 配置Nacos地址,需要注意的是配置一定不能出错,否则读取不到配置信息

spring:
  application:
    name: userservice # 服务名称
  profiles:
    active: dev # 环境
  cloud:
    nacos:
      server-addr: localhost:8848 # Nacos 地址
      config:
        file-extension: yaml # 文件后缀

配置中的:name-active.file-extension 组成了Nacos 配置管理中文件的名字

3.这里在controller 层写了一个请求现在时间的映射,而现在日期的格式化采用的是Nacos中配置的pattern

  • @RefreshScope: 开启Nacos 热更新
  • @Value("${pattern.dateformat}"): 注入Nacos 中配置的值
package cn.itcast.user.web;

import cn.itcast.user.pojo.User;
import cn.itcast.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.core.env.Environment;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Slf4j
@RefreshScope
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Value("${pattern.dateformat}")  //注入Nacos 配置管理中的配置信息
    private String dateformat;  


    @GetMapping("/now")
    public String now(){
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat));
    }
}

修改前:

修改patter 格式后请求,不用重启服务就可以使用到最新的patter:

同时控制台也有相关配置更新的日志输出:

热更新方式二

1.新建配置类

package cn.itcast.user.config;

import lombok.Data;
import org.checkerframework.checker.units.qual.C;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "pattern")
public class PatternConfig {
    private String dateformat;
}

2.controller 直接注入使用

不用再使用 @RefreshScope 注解标记

package cn.itcast.user.web;

import cn.itcast.user.config.PatternConfig;
import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {


    @Autowired
    private PatternConfig patternConfig;

    @GetMapping("/now")
    public String now(){
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(patternConfig.getDateformat()));
    }


}

修改格式之前:

修改格式之后:

控制台收到变更通知:

Nacos 多环境配置共享

场景:开发、测试、生产环境 该配置的值都是一样,那么即可以将该值配置在共享配置文件中

微服务启动时会从nacos读取多个配置文件:

  • [spring.application.name]-[spring.profiles.active].yaml, 例如:usercervice-dev.yaml
  • [spring.application.name].yaml,例如:userservice.yaml

无论profile 如何变化,[spring.application.name].yaml 这个文件一定会加载,因此多环境共享配置可以写入这个文件

案例:
1.新建一个userservice.yaml:

2.配置类引入该属性:

package cn.itcast.user.config;

import lombok.Data;
import org.checkerframework.checker.units.qual.C;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Data
@Component
@ConfigurationProperties(prefix = "pattern")
public class PatternConfig {
    private String dateformat;
    private String envShare;
}

3.controller 映射直接返回配置类:

    @GetMapping("/prop")
    public PatternConfig prop(){
        return patternConfig;
    }

启动微服务的配置:
userservice 8081: spring.profiles.active=dev
userservice 8082: spring.profiles.active=test

结果:

userservice 8081 加载的配置文件:

userservice 8082 加载的配置文件:

多种配置的优先级:

posted @ 2023-09-03 20:41  chuangzhou  阅读(20)  评论(0编辑  收藏  举报