likes
comments
collection
share

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

作者站长头像
站长
· 阅读数 3

上一篇讲解的通过RestTemplate完成远程调用存在什么问题?

1.把提供者的地址写死在代码中,提供者部署的服务发生改变。那么消费者也要改变。

  1. 如果提供者是一个集群,那么消费者如何负载均衡的调用

我们如果想解决上述问题 我们需要使用注册中心。

注册中心

服务治理是微服务架构中最核心最基本的模块。用于实现各个微服务的自动化注册与发现

服务注册: 在服务治理框架中,都会构建一个 **注册中心 **,每个服务单元向注册中心登记自己提供服

务的详细信息。并在注册中心形成一张服务的 **清单 **,服务注册中心需要以 **心跳30s 90s **的方式去监测清单中 的服务是否可用,如果不可用,需要在服务清单中剔除不可用的服务。

服务发现: 服务调用方向服务注册中心咨询服务,并获取 **所有服务 **的实例清单,实现对具体服务实

例的访问。

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

通过上面的调用图会发现,除了微服务,还有一个组件是服务注册中心,它是微服务架构非常重要

的一个组件,在微服务架构里主要起到了协调者的一个作用。注册中心一般包含如下几个功能:

  1. 服务发现:

服务注册:保存服务提供者和服务调用者的信息

服务订阅:服务调用者订阅服务提供者的信息,注册中心向订阅者推送提供者的信息

  1. 服务配置:

配置订阅:服务提供者和服务调用者订阅微服务相关的配置

配置下发:主动将配置推送给服务提供者和服务调用者

  1. 服务健康检测

检测服务提供者的健康情况,如果发现异常,执行服务剔除

常见的注册中心组件有哪些?

nacos:---它是阿里巴巴的组件.

eureka: ---它是netflix公司的组件---该组件已经停止更新

zookeeper---它是apache公司的

1.下载nacos注册中心

下载地址: github.com/alibaba/nac…

默认它启动模式为--集群模式---修改它为单机模式

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

启动脚本

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

访问:

http://localhost:8848/nacos

账号和密码: nacos

微服务注册和拉取注册中心的内容

服务提供端

(1)引入nacos的依赖

<!--nacos的依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

(2) 配置注册中心的地址--默认本地端口号8848

#配置nacos的地址
spring.cloud.nacos.server-addr=localhost:8848
#为微服务定义名称
spring.application.name=cjj-product

(3)进入nacos服务列表查看服务

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

(4)消费端

(1)引入nacos依赖

<!--nacos的依赖-->
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

(2)配置注册中心的地址

#为微服务定义名称
spring.application.name=cjj-order
#nacos地址,
spring.cloud.nacos.server-addr=localhost:8848

(3)修改controller层的代码

@RestController
@RequestMapping("order")
public class OrderController {

    @Autowired
    private OrderServer orderServer;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private DiscoveryClient client;

    @GetMapping("insertOrder")
    public String insertOrder(Integer pid,Integer number){
        final Order order = new Order();
        order.setUid(3);
        order.setUsername("aguang");
        order.setNumber(number);


        //从哪个微服务拉取
        final List<ServiceInstance> instances = client.getInstances("cjj-product");
   
        //访问微服务集群中的某个服务--这里是下标为0的服务
        final ServiceInstance serviceInstance = instances.get(0);
        final URI uri = serviceInstance.getUri();


        final Product product = restTemplate.getForObject(uri+"/product/findProductById/" + pid, Product.class);
        order.setPid(product.getPid());
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());

        final Integer integer = orderServer.insertOrder(order);
        return integer>0?"下单成功":"下单失败";

    }
}

Ribbon实现负载均衡

1.什么是负载均衡

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

根据负载均衡发生位置的不同,一般分为服务端负载均衡客户端负载均衡

服务端负载均衡指的是发生在服务提供者一方,比如常见的nginx负载均衡

而客户端负载均衡指的是发生在服务请求的一方,也就是在发送请求之前已经选好了由哪个实例处理请求

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

我们在微服务调用关系中一般会选择 **客户端负载均衡 **,也就是在服务调用的一方来决定服务由哪个提供者执行.

2.演示:---手动完成负载均衡

手动开启两个提供端

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

controller

@RestController
@RequestMapping("order")
public class OrderController {

    @Autowired
    private OrderServer orderServer;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private DiscoveryClient client;

    @GetMapping("insertOrder")
    public String insertOrder(Integer pid,Integer number){
        final Order order = new Order();
        order.setUid(3);
        order.setUsername("aguang");
        order.setNumber(number);


        //从哪个微服务拉取
        final List<ServiceInstance> instances = client.getInstances("cjj-product");
        //随机下标
        final int i = new Random().nextInt(instances.size());
        //随机访问微服务集群中的某个服务--随机策略
        final ServiceInstance serviceInstance = instances.get(i);
        final URI uri = serviceInstance.getUri();


        final Product product = restTemplate.getForObject(uri+"/product/findProductById/" + pid, Product.class);
        order.setPid(product.getPid());
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());

        final Integer integer = orderServer.insertOrder(order);
        return integer>0?"下单成功":"下单失败";

    }
}

上面通过手动完成了负载均衡的调用,存在的问题: 它采用的随机负载均衡,如果我想使用轮询负载均衡策略。只能修改源代码。这势必会造成代码的耦合。---springcloud提供了一个组件--可以灵活的完成负载均衡。--ribbon

3.基于Ribbon实现负载均衡

Ribbon利用从nacos中读取到的服务信息,在调用服务节点提供的服务时,会合理(策略)的进行负载。在Springcloud中,可以将注册中心和Rabbion配合使用,Ribbon自动的从注册中心获取服务者提供的列表信息,并基于内置的负载均衡算法,请求服务。

Rbibon的主要作用

(1)服务调用

基于Ribbon实习那服务调用,是通过拉取到的所有服务列表组成,(服务名-请求路径的)映射关系,借助ReatTemplate最终进行调用

(2)负载均衡

当有多个服务提供者的时候,Ribbon可以根据负载均衡的算法,自动选择需要调用的服务地址

1.告诉restTemplate使用ribbon完成负载均衡

 /**
  * 注入RestTemplate用来实现http远程调用
  * @return
  */
@Bean
//告诉restTemplate将Ribbon作为负载均衡器
@LoadBalanced
 public RestTemplate restTemplate(){
    final RestTemplate restTemplate = new RestTemplate();
    return restTemplate;
}

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

2.修改controller

@RestController
@RequestMapping("order")
public class OrderController {

    @Autowired
    private OrderServer orderServer;
    @Autowired
    private RestTemplate restTemplate;

    @GetMapping("insertOrder")
    public String insertOrder(Integer pid,Integer number){
        final Order order = new Order();
        order.setUid(3);
        order.setUsername("aguang");
        order.setNumber(number);


        //Ribbon默认采用的是轮询策略
        final Product product = restTemplate.getForObject("http://cjj-product/product/findProductById/" + pid, Product.class);
        order.setPid(product.getPid());
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());

        final Integer integer = orderServer.insertOrder(order);
        return integer>0?"下单成功":"下单失败";

    }
}

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

3.测试

4.Ribbon的负载均衡策略有哪些,以及如何修改

Ribbon负载均衡的七种策略cjj
id策略名称策略对应的类名实现原理
1轮询策略RoundRobinRule轮询策略表示每次都顺序的选取下一个provider,比如一共有五个procider,第一次取第一个,第二次选第二个,以此类推
2权重轮询策略WeightedResponseTimeRule1.根据每个procider的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性越低。2.原理:一开始为轮询策略,并开启计时器,每30s手机一次每个provider的平均响应时间,当信息足够时,给每个peocider附上一个权重,并按照权重随机选择procider,高权重的procider会被高概率选中
3随机策略RandomRule从provider列表中随机选择一个provider
4最少并发数策略BestAvailableRule选择正在请求中的并发数最小的provider,除非这个provider在熔断中
5在"选定的负载均衡策略"基础上进行重试机制RetryRule1.“选定的负载均衡策略”这个策略是沦胥你策略RoundRobinRule 2.该重试策略先设定一个阈值时间段,如果在这个阈值时间段内,当选择provider不成功,则一直尝试采用选择“选定的负载均衡策略:轮询策略” 最后选择一个可用的provider
6可用敏感策略AvailabilityFiteringRule过滤性能差的provider有两种:第一种:过滤掉在eureka中处于一直连接失败的provider 第二种:过滤掉高并发的provider
7区域敏感性策略ZoneAvoidanceRule1.以一个区域为单位考察可用性,对于不可用的区域整个丢弃,从剩下的区域中选可用的provider 2.如果这个ip区域内有一个或多个实例不可达或相应变慢,都会降低该ip区域内其他ip被选中的权重。

上面是ribbon内置的负载均衡策略,我们也可以自定义负载均衡。

5.如何改变ribbon的负载均衡策略---修改配置文件

修改配置文件

#修改ribbon的负载均衡策略为随机策略
cjj-product.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

openfeign完成服务调用

什么是OpenFeign。

OpenFeign是Spring Cloud提供的一个声明式的伪Http客户端, 它使得调用远程服务就像调用本地方法一样简单, 只需要创建一个接口并添加一个注解即可。

Nacos很好的兼容了OpenFeign, OpenFeign负载均衡默认集成了 Ribbon, 所以在Nacos下使用OpenFeign默认就实现了负载均衡的效果。

完成openfeign的调用

(1)依赖

<!--        openfeign的依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

(2)创建openfeign接口

//供给端的服务名
@FeignClient(value = "cjj-product")
public interface ProductFeign {

    //接口的方法,必须和被调用者的接口参数完全一致,路径也完全一致
    @GetMapping("/product/findProductById/{pid}")
    public Product findProductById(@PathVariable Integer pid);
}

(3)开启openfeign注解驱动

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

(4)修改controller

@RestController
@RequestMapping("order")
public class OrderController {

    @Autowired
    private OrderServer orderServer;

    //注入定义的openfeign接口
    @Autowired
    private ProductFeign productFeign;

    @GetMapping("insertOrder")
    public String insertOrder(Integer pid,Integer number){
        final Order order = new Order();
        order.setUid(3);
        order.setUsername("aguang");
        order.setNumber(number);


        //使用openfeign远程调用,完成服务的调用
        final Product product = productFeign.findProductById(pid);
        order.setPid(product.getPid());
        order.setPname(product.getPname());
        order.setPprice(product.getPprice());

        final Integer integer = orderServer.insertOrder(order);
        return integer>0?"下单成功":"下单失败";

    }
}

springcloud--nacos注册中心--Ribbon负载均衡--openfeign服务调用

gateway网关

转载自:https://juejin.cn/post/7255876429517504567
评论
请登录