学习目标:

  • Nacos注册中心
  • Nacos配置中心
  • Nacos集群和持久化
  • 负载均衡Ribbon
  • 声明式服务调用Feign

    Nacos注册中心


    一、nacos的安装和启动

   1.解压

[root@localhost ~]# cd /usr/upload
[root@localhost upload]# tar -zxvf nacos-server-1.4.1.tar.gz -C /usr/local    

    2.启动和关闭

     启动:

 [root@localhost local]# cd nacos/bin/
 [root@localhost bin]# ./startup.sh -m standalone #非集群模式启动

    关闭:

[root@localhost bin]# ./shutdown.sh

二、Nacos注册中心

注册中心主要有三部分组成:

Ø Nacos-Server:注册中心

提供服务的注册和发现。

Ø Nacos-Provider:服务提供方

把自身的服务实例注册到 Nacos Server 中

Ø Nacos-Consumer:服务调用方

通过 Nacos Server 获取服务列表,消费服务。

1.服务提供者: nacos_provide

        1. pom.xml文件

 <!--nacos客户端-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        2. application.yml

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.216.133:8848 #nacos服务的地址
  application:
    name: nacos-provider #向注册中心注册的名字

        3.App(启动类)

@SpringBootApplication
@EnableDiscoveryClient//向注册中心注册该服务,并可以获取其他服务的调用地址
public class ProviderApp {

    public static void main(String[] args) {
        SpringApplication.run(ProviderApp.class,args);
    }
}

2.服务消费者:nacos_consumer

        1.pom.xml

 <!--nacos客户端-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        2.application.yml

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.216.133:8848 #nacos服务的地址
  application:
    name: nacos-consumer #向注册中心注册的名字

        3.App

@SpringBootApplication
@EnableDiscoveryClient//向注册中心注册该服务,并可以获取其他服务的调用地址
public class ConsumerApp {

    public static void main(String[] args) {
        SpringApplication.run(ConsumerApp.class,args);
    }
}

3.为什么要使用注册中心 

  1.  地址硬编码

 不能负载均衡              


Nacos配置中心    

一、nacos——config

        1. pom.xml

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--nacos注册中心的启动器-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--nacos配置中心的启动器-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>
        <dependency>
            <groupId>ccom.zzcsy</groupId>
            <artifactId>springcloud_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        2. bootstrap.yml

spring:
  cloud:
    nacos:
      config:
        server-addr: 192.168.216.133:8848
        file-extension: yaml #后缀名,只支持 properties 和 yaml 类型
        prefix: nacos-config #文件名,如果没有配置则默认为 ${spring.appliction.name}

        3. 在nacos中创建配置文件                

                Data ID:

${spring.cloud.nacos.config.prefix}.${spring.cloud.nacos.config.file-extension}

                 配置格式:yaml或properties

  • spring.cloud.nacos.config.prefix:默认是当前服务的服务名称

  • spring.cloud.nacos.config.file-extension:配置文件的格式(后缀),目前只支持yaml和properties

                例如:

spring:
  cloud:
    nacos:
      config:
        server-addr: 192.168.216.133:8848 #配置中心的地址
        file-extension: yaml #配置文件扩展名只支持properties和yaml
        prefix: nacos-config #文件名,默认是spring.application.name

二、为什么要使用配置中心


  1. 集中管理配置文件
  2. 动态更新配置文件

三、隔离模型


Namespace Group DataId介绍:

  •  Namespace: 代表不同的环境的配置隔离 ,如:开发、测试、生产等
  •  Group: 可以代表某个项目,如health、JD 
  •  DataId: 每个项目下的工程名     

获取配置集需要指定:

  • nacos服务地址,必须指定

  • namespace,如不指定默认public

  • group,如不指定默认 DEFAULT_GROUP

  • dataId,必须指定


    持久化


    一、修改conf/application.properties文件

### If use MySQL as datasource:
spring.datasource.platform=mysql

### Count of DB:
db.num=1

### Connect URL of DB:
db.url.0=jdbc:mysql://192.168.216.130:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=1111

     二、建库建表     

          创建nacos库   注意:库名和application.properties中的库名保持一致

          建表:找到conf/nacos-mysql.sql文件并执行

           测试
              1、重启nacos
              2、新建配置文件
              3、观察配置文件是否持久化到mysql中 


集群


一、节点规划

节点 端口
192.168.204.156 8848
192.168.204.156 8849
192.168.204.156 8850

二、集群搭建

        1、找到conf/cluster.conf.example ,将其改名为 conf/cluster.conf

# ip:port
192.168.216.133:8848
192.168.216.133:8849
192.168.216.133:8850

        2、复制三份Nacos

[root@localhost bin]# cd /usr/local
[root@localhost java]# mkdir nacos_cluster
[root@localhost java]# cp -r nacos nacos_cluster/nacos_8848
[root@localhost java]# cp -r nacos nacos_cluster/nacos_8849
[root@localhost java]# cp -r nacos nacos_cluster/nacos_8850

        3、将 conf/application.properties 中的端口号分别改为:

server.port=8848
server.port=8849
server.port=8850

三、配置代理服务

  1. 安装ngnix
  2. 配置ngnix代理nacos
  3. 测试
    1. 启动nacos集群
    2. 启动ngnix
    3. 将微服务注册到nacos集群
    4. 访问nacos集群

负载均衡Ribbon


一、什么是Ribbon

       ribbon是基于netflix 实现的一个工作在consumer端的负载均衡工具,提供了很多负载均衡策略:轮询、随机等。

二、实现自定义负载均衡

        1、创建服务提供者

                1、创建工程provider

                 2、application.yml

server:
  port: 9090
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.216.133:8848
  application:
    name: ribbon-provider

server:
  port: 9091
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.216.133:8848
  application:
    name: ribbon-provider

        2、创建服务消费者

                1、创建工程nacos_consumer

                2、application.yml

server:
  port: 80
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.216.133:8848
  application:
    name: ribbon-consumer

                3、controller

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

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private DiscoveryClient discoveryClient;//发现服务的工具类

    private int index;

    @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable Integer id) {

        List<String> serviceList = discoveryClient.getServices();

        //随机方式获得服务
        int currentIndex = new Random().nextInt(2);

        //轮询方式获得服务
        //index = index + 1;
        //int currentIndex =(index)% serviceList.size();

        获取nacos中注册的指定服务信息
        ServiceInstance instance = discoveryClient.getInstances("ribbon-provider").get(currentIndex);
        String url = "http://" + instance.getHost() + ":" + instance.getPort() + "/provider/getUserById/" + id;

        return restTemplate.getForObject(url, User.class);
    }
}

二、什么是负载均衡

        负载均衡就是将负载(工作任务,访问请求)进行分摊到多个操作单元(服务器,组件)上进行执行。

        1.开启ribbon负载均衡

   @Bean
   @LoadBalanced//开启ribbon负载均衡,默认是轮询策略
    public RestTemplate restTemplate(){
       return new RestTemplate();
   }

        添加了@LoadBalanced注解之后,Ribbon会给restTemplate请求添加一个拦截器,在拦截器中获取 注册中心的服务列表,并使用Ribbon内置的负载均衡算法从服务列表里选中一个服务,通过获取到的服务信息 (ip,port)替换 serviceId 实现负载请求。

        2、指定负载均衡的策略

//随机策略
	@Bean
	public IRule iRule() {
		return new RandomRule();
	}
负载均衡常用的的几种策略
负载均衡实现 策略
随机策略:RandomRule 从服务提供者的列表中随机选择一个服务实例
轮询策略:RoundRobinRule 按照一定的顺序依次调用服务实例
可用敏感性策略:AvailabilityFilteringRule 先过滤掉由于多次访问故障的服务,以及并发连接数超过阈值的服务,然后对剩下的服务按照轮询策略进行访问
权重策略:WeightedResponseTimeRule    根据平均响应时间计算所有服务的权重,响 应时间越快服务权重就越大被选中的概率即越高,如果服务刚启动时统计信息不足,则 使用RoundRobinRule策略,待统计信息足够会切换到该WeightedResponseTimeRule策略
 

重试负载均衡策:

RetryRule

先按照 RoundRobinRule 策略获取 provider,若获取失败,则在指定的时限内重试。默认的时限为 500 毫秒。
最小连接数策略:BestAvailableRule 先过滤掉由于多次访问故障的服务,然后选择一个并发量最小的服务
区域敏感策略:ZoneAvoidanceRule  综合判断服务节点所在区域的性能和服务节点的可用性,来决定选择哪个服务

        3、发送请求

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

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private DiscoveryClient discoveryClient;//发现服务的工具类

    @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable Integer id) {

    String url = "http://ribbon-provider/provider/getUserById/"+id;
    return restTemplate.getForObject(url, User.class);
    }
}

三、ribbon存在的问题

        url和参数还需要拼接,效率太低,不利于维护。


声明式服务调用Feign


一、背景

        前文我们已经学到,当我们通过RestTemplate调用其它服务的API时,所需要的参数须在请求的URL中进行拼接,如果参数少的话或许我们还可以忍受,一旦有多个参数的话,这时拼接请求字符串就会效率低下,并且显得好傻

        那么有没有更好的解决方案呢?答案是确定的有,Netflix已经为我们提供了一个框架:Feign。


二、Feign概述

        Feign是Spring Cloud提供的声明式、模板化的HTTP客户端, 它使得调用远程服务就像调用本地服务一样简单,只需要创建一个接口并添加一个注解即可。工作在consumer端。

        Spring Cloud集成Feign并对其进行了增强,使Feign支持了Spring MVC注解;Feign默认集成了Ribbon,所以Fegin默认就实现了负载均衡的效果。

        ribbon + restTemplate  优化后 = feign


三、Fegin入门

 1、创建工程

        1、 拷贝ribbon_provider_1

                

        2、application.yml

server:
  port: 9090
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.216.133:8848
  application:
    name: feign-provider

 2、创建feign接口

         1、创建工程

               

        2、pom.xml

 <dependencies>
        <!--Spring Cloud OpenFeign Starter -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.bjpowernode</groupId>
            <artifactId>springcloud_common</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

        3、feign

@FeignClient("feign-provider")
@RequestMapping("/provider")
public interface UserFeign {

    @RequestMapping("/getUserById/{id}")
    public User getUserById(@PathVariable("id") Integer id);
}

3、创建服务消费者

        1.创建工程

         2、pom.xml

        <!--feign接口-->
        <dependency>
            <groupId>com.zzcsy</groupId>
            <artifactId>feign_interface</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        3、controller

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

   @Autowired
    private UserFeign userFeign;//代理类

   @RequestMapping("/getUserById/{id}")
   public User getUserById(@PathVariable Integer id){
       System.out.println(userFeign.getClass());
       return userFeign.getUserById(id);
   }
}

        4、App


四、feign原理

        1、将Feign接口代理类注入到Spring容器中

                 @EnableFeignClients开启feign注解扫描,调用FeignClientsRegistrar.registerFeignClients()方法扫描@FeignClient注解的接口生成代理类,并把接口和代理类交给Spring的容器管理。

        2、为接口的方法创建RequestTemplate

                当consumer调用feign代理类时,代理类会调用SynchronousMethodHandler.invoke()创建RequestTemplate(url,参数)

        3、发起请求

                ​​​​​​​代理类会通过RequestTemplate创建Request,然后client(URLConnetct、HttpClient、OkHttp)使用Request发送请求


五、feign参数传递

传参方式:

  • restful风格:

               @PathVarible【拼接restful形式的url】

  • ?传参

               @RequestParam【拼接?形式的url】

  • pojo参数

                @RequestBody User user【获取请求体中的json串】

        

        


版权声明:本文为qq_44997403原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_44997403/article/details/126352397