nacos简单介绍

下载 nacos

下载后就是一个压缩包

启动nacos命令
startup.cmd -m standalone

linux 命令是
./startup.sh -m standalone

nacos 是进行服务的注册管理
比如想要编写一个 注册服务
需要将当前的服务 进行注册
注册之后 可以在nacos 里进行管理

服务的注册

xml文件里面继承一个父工程

<parent>
    <artifactId>01-sca</artifactId>
    <groupId>com.jt</groupId>
    <version>1.0-SNAPSHOT</version>
</parent>

创建服务

<dependencies>
    <!--
        创建服务 必须注册服务
        注册服务 前提是 web 服务
    -->
    <!--web 服务 默认有tomcat-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

服务的注册和发现

<dependencies>
    <!-- 服务的注册和发现
        添加完成后 启动时 会向nacos 服务发送一些 心跳包 进行服务注册
        添加了这个 依赖之后 表示 此项目是nacos 服务的一个客户端对象
    -->
    <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
    </dependency>

</dependencies>

resources 文件夹里创建application.yml文件

# 配置服务的端口
server:
  port: 8081
# 服务名   一般是自己的项目名称
spring:
  application:
    name: sca-provider
# 服务的注册地址  服务启动时向这个 地址返送 包
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848

创建启动类

@SpringBootApplication
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}
服务的调用

编写controller

@RestController //相当于Controller注解和ResponseBody注解
public class ProviderController {

    @Value("${server.port:8080}") //在参数后面加上参数表示 默认值
    // 如果 server.port 没有获取到 将使用默认值
    private String server;

    @GetMapping("/provider/echo/{msg}")
    // 在PathVariable注解里面的参数是为了 老版本的维护
    // 代表 {msg} 传来的参数
    public String doGetDemo(@PathVariable("msg") String msg){

        return "say hello "+msg+" 端口 "+server;
    }
}

创建其他工程用来进行调用

添加web和服务注册依赖
添加application.yml

远端服务调用

编写启动类

@SpringBootApplication
/* 启动类 本身就是一个 配置类 其他类需要调用 直接在此处注入 */
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
    /**
     * RestTemplate 是由spring 提供的远程 服务的调用
     *
     * 例如 sca-consumer 调用sca-provider
     * */
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

编写controller

@RestController
public class ConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 访问 http://localhost:8090/consumer/doRestDemo
     *
     * 内部 基于 RestTemplate 进行远端服务调用
     * */
    @GetMapping("/consumer/dRestDemo")
    public String doRestDemo(){
        // 远程调用的 请求地址
        String url = "http://localhost:8081/provider/echo/狗蛋";

        // 1.请求地址  2.响应返回的数据类型   3.参数
        return restTemplate.getForObject(url, String.class);
    }
}

当用户访问/consumer/dRestDemo
内部进行远程调用http://localhost:8081/provider/echo/狗蛋
并进行响应返回

负载均衡

如果请求的实例只有一个 但是
请求地址有多个
实现了负载均衡

spring-cloud提供了LoadBalancerClient 对象
此对象可以获取 nacos 中的服务实例

/**
 * 此对象可以获取 nacos 中的服务实例
 * 通过 负载均衡算法 从所有实例中取其中一个
 * */
@Autowired // 负载均衡 客户端 对象 spring cloud提供
private LoadBalancerClient loadBalancerClient;

// 动态获取 当前实例名称
@Value("${spring.application.name:狗蛋}")
private String appName;

@GetMapping("/consumer/dRestDemo2")
public String doRestDemo2(){

    // 选择服务 ID  从nacos 获取服务实例 内置了负载均衡
    ServiceInstance instance = loadBalancerClient.choose("sca-provider");

    // 获取IP 地址
    String ip = instance.getHost();

    // 获取端口号
    int port = instance.getPort();

    // 使用了负载均衡 地址 需要动态变化
    String url = "http://"+ip+":"+port+"/provider/echo/"+appName;
    // 上面的字符串写法 太生硬 使用 string 提供的一个api
    // %s 代表一个占位符 字符串类型   %d代表数组
    String url2 = String.format("http://%s:%s/provider/echo/%s",ip,port,appName);

    // 1.请求地址  2.响应返回的数据类型   3.参数
    return restTemplate.getForObject(url, String.class);
}
方法二@LoadBalanced

使用@LoadBalanced注解
描述 RestTemplate 对象
系统底层会基于 RestTemplate 进行 远程服务调用 会被一个拦截器拦截 进行功能增强
增强指 基于 loadBalancerClient 对象进行服务实例获取 并进行功能添加
服务实例获取过程 底层采用 负载均衡

/**
 * 使用@LoadBalanced
 * 描述 RestTemplate 对象
 * 系统底层会基于 RestTemplate 进行 远程服务调用 会被一个拦截器拦截 进行功能增强
 * 拦截器 (Interceptor)
 * 增强指 基于loadBalancerClient对象进行服务实例获取 并进行功能添加
 * 服务实例获取过程 底层采用 负载均衡
 * */
@Bean
@LoadBalanced
public RestTemplate loadBalancedRestTemplate(){
    return new RestTemplate();
}

使用

进行注入

/**
 * 存入在Spring 管理容器里是一个 方法名 所以这里
 * 遇到相同的 实例对象 会查找 方法名
 * */
@Autowired
private RestTemplate loadBalancedRestTemplate;

@GetMapping("/consumer/dRestDemo3")
public String doRestDemo3(){

    // 地址直接写 项目名称 sca-provider
    // 增强工具直接会通过 名称进行查找
    String url = String.format("http://sca-provider/provider/echo/%s",appName);

    // 1.请求地址  2.响应返回的数据类型   3.参数
    return loadBalancedRestTemplate.getForObject(url, String.class);
}

底层默认的负载均衡策略是
轮询策略
RoundRobinRule

更改负载均衡策略

最简单的方式在配置类里添加方法

/**
 * 更改默认的负载均衡策略
 * 这种配置方式不够灵活
 * 项目上线之后 打包成jar包 再去调整不灵活
 * */
@Bean
public IRule rule(){

    return new RandomRule();
}

或者

更改application.yml

# 配置 sca-provider 服务的负载均衡配置 sca-provider是服务名
sca-provider:
  ribbon: #ribbon 是一个负载均衡组件 是Ribbon 组件中提供了 IRule 接口及相关实现
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

总共的负载均衡方法

01

基于Feign的远程服务调用

通过Feign可以 简化 服务 对远程服务的调用

添加feign组件
进行远程服务调用

<!--添加feign组件 进行远程服务调用-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

编辑启动类
添加@EnableFeignClients注解

/**
 * 注解用于描述一些配置类
 * 告诉系统 启动时为@FeignClient注解描述的接口创建实现了及对象
 * 交给Spring管理
 * */
@EnableFeignClients
@SpringBootApplication
/* 启动类 本身就是一个 配置类 其他类需要调用 直接在此处注入 */
public class ConsumerApplication {
    public static void main(String[] args) {

        SpringApplication.run(ConsumerApplication.class, args);
    }
}

创建一个抽象类

/**
 * 用于描述远程服务的接口
 * value 两层意思
 * 1. 调用的远程服务名
 * 2. 当前spring 管理bean的名字key
 * */
@FeignClient("sca-provider") // 声明调用哪一个服务 sca-provider服务
public interface RemoteProviderService {

    @GetMapping("/provider/echo/{msg}")// 声明调用的哪一个方法/接口
    String echoMessage(@PathVariable("msg") String msg);
    // @PathVariable("msg") 定义接收参数是 msg 必须写
}

使用

@RestController
@RequestMapping("/consumer")
public class FeignConsumerController {

    @Autowired
    private RemoteProviderService remoteProviderService;

    @GetMapping("/echo/{msg}")
    public String doFeignEcho(@PathVariable String msg){
        //远程服务调用
        return remoteProviderService.echoMessage(msg);
    }
}

如果有多个抽象类同时 调用一个 服务

FeignClient 注解里面添加contextId 属性

@FeignClient(name="sca-provider",contextId="remoteProviderService")
//sca-provider为服务提供者名称
interface RemoteProviderService{
    @GetMapping("/provider/echo/{string}")//前提是远端需要有这个服务
    public String echoMessage(@PathVariable("string") String string);
}
远程服务未响应

请求过程中会出现异常或超时
应该返回一个备用方案

设置一个ProviderFallbackFactory
实现FallbackFactory接口并添加泛型处理对象的泛型

/**
 * 基于此对象处理
 * RemoteProviderService 接口调用时出现的服务中断,超时等问题
 */
@Component
public class ProviderFallbackFactory implements FallbackFactory<RemoteProviderService> {
    /**
     * 此方法会在 RemoteProviderService 接口服务调用时,出现了异常后执行.
     * 用于接收异常
     */
    @Override
    public RemoteProviderService create(Throwable throwable) {
        return new RemoteProviderService() {
            @Override
            public String echoMessage(String msg) {
                return "请求超时 过后访问";
            }
        };
    }
}

并配置yml文件
开启熔断机制
启动备选方案

# 开启熔断机制 启动备选方案
feign:
  hystrix:
    enabled: true

当远程服务超时将会访问备选方案

服务的配置中心

除了代码之外 软件还有一些配置信息
比如数据库的用户名和密码
不停机就可以动态刷新服务内部的配置项

Nacos配置入门
演示日志

运行程序时进行日志输出

创建Controller对象 如

@RestController //交给 spring 进行管理
public class ProviderLogController {

    //  使用 org.slf4j.Logger Java中的日志API规范
    //  log对象在哪个类中创建,getLogger方法中的就传入哪个类的字节码对象
    // 使用 org.slf4j.LoggerFactory 提供的方法
    // 可以传入字节码对象 或者 包名类名
    // private static final Logger log= LoggerFactory.getLogger("com.jt.provider.controller.ProviderLogController");
    private static final Logger log= LoggerFactory.getLogger(ProviderLogController.class);

    // http://localhost:8081/provider/log/doLog01
    @GetMapping("/provider/log/doLog01")
    public String doLog01(){
        System.out.println("=== sys提供的打印 ===");
        log.trace("=== log for trace ===");
        log.debug("=== log for debug ===");
        log.info("=== log for info ===");
        log.warn("=== log for warn ===");
        log.error("=== log for error ===");
        return "test log 01";
    }
}

访问之后会打印

=== sys提供的打印 ===
2021-12-23 10:38:05.570  INFO 16072 --- [nio-8081-exec-1] c.j.p.controller.ProviderLogController   : === log for info ===
2021-12-23 10:38:05.571  WARN 16072 --- [nio-8081-exec-1] c.j.p.controller.ProviderLogController   : === log for warn ===
2021-12-23 10:38:05.571 ERROR 16072 --- [nio-8081-exec-1] c.j.p.controller.ProviderLogController   : === log for error ===

打印顺序trace < debug < info < warn < error
yml文件配置

# 更换日志输出
logging:
  level:
    com.jt: debug
Nacos配置中心

导入xml依赖
添加配置服务依赖

<!-- 服务的配置 -->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>

更新配置
resources下更新yml文件

# 配置服务的端口
server:
  port: 8081
# 服务名   一般是自己的项目名称
spring:
  application:
    name: sca-provider
# 服务的注册地址  服务启动时向这个 地址返送 包
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
      config:
        server-addr: localhost:8848
        file-extension: yml

nacos配置中心新建配置
01

resources文件里的yml文件更改为
bootstrap.yml
如果不进行更改 将不生效

只需要更改Nacos配置中心的文件项目也会进行更改
无需重新运行

自己所写 的配置文件权限最大

Nacos配置管理模型

Nacos 配置管理模型是由三部分组成

  1. Namespace 命名空间 对不同环境进行隔离
    如: 开发环境和生产环境

  2. Group 分组,将若干个服务或若干个配置归为一组

  3. service/Datald 某一个服务或配置集, 一般对应一个配置文件

命名空间设置

Nacos中命名空间里面新建命名空间
输入别名和描述之后
会提供一个命名空间的ID

将之前的配置添加到新的命名空间
之后配置文件里进行设置

# 服务名   一般是自己的项目名称
spring:
  application:
    name: sca-provider
# 服务的注册地址  服务启动时向这个 地址返送 包
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848
      config:
        server-addr: localhost:8848 #从这个地址 查找配置中心 的配置文件
        file-extension: yml
        namespace: 511075eb-b633-41a9-a0fe-669fee9bb83c #默认是 public 进行更改命名空间

将自动读取新的命名空间的配置

分组设置

一个服务在不同时间节点切换不同的配置
使用到分组设计实现

Nacos配置管理里
新建配置时 重新写一个Group分组

02

Java配置文件里面

config:
 server-addr: localhost:8848 #从这个地址 查找配置中心 的配置文件
 file-extension: yml
 namespace: 511075eb-b633-41a9-a0fe-669fee9bb83c #默认是 public 进行更改命名空间
 group: DEFAULT_GROUP_51 # 配置分组默认是 DEFAULT_GROUP

Controller类中读取配置

@RefreshScope
@RestController
public class ProviderCacheController {

    @Value("${goudan:false}")
    private boolean goudan;


    @GetMapping("/provider/cache01")
    public String doCache01(){

        return "读取配置文件内容是 "+goudan;
    }
}
共享配置

多个配置文件中都有相同配置时
可以将这些配置进行提取

nacos创建共享配置

01

配置文件yml文件

# 公共配置
shared-configs[0]:
 data-id: app-public.yml # 公共配置文件名称
 refresh: true # 开启动态更新

读取公共配置

@RefreshScope
@RestController
public class ProviderSecretController {

    @Value("${app.ser:7777}")
    private String ser;

    @GetMapping("/provider/doGetSec")
    public String doGetSec(){

        return "this is num "+ser;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值