六.SpringCloud极简入门-客户端负载均衡Ribbon

老鸟飞过 , 学习使用,欢迎交流

六.客户端负载均衡Ribbon+RestTemplate

1.基本概念

1.1.为什么要Ribbon

我们知道,为了防止应用出现单节点故障问题,同时为了提高应用的作业能力,我们需要对应用做集群 ,如果我们对user-server(用户服务)做了集群 ,那么这个时候回衍生出一些问题:现在有两个user-server(用户服务)就意味着有两个user-server(用户服务)的通信地址,我的order-server(订单服务)在向user-server(用户服务)发起调用的时候该访问哪个?如何访问?这个时候就需要有一个组件帮我们做请求的分发,即:负载均衡器,而Ribbon就是一个客户端负载均衡器。

1.2.什么是Ribbon

Ribbon是Netflix发布的云中间层服务开源项目,主要功能是提供客户端负载均衡算法。Ribbon客户端组件提供一系列完善的配置项,如,连接超时,重试等。简单的说,Ribbon是一个客户端负载均衡器,Ribbon可以按照负载均衡算法(如简单轮询,随机连接等)向多个服务发起调用(正好可以解决上面的问题),我们也很容易使用Ribbon实现自定义的负载均衡算法。

1.3.Ribbon的工作机制

如下图,我们将user-server(用户服务)做集群处理,增加到2个节点(注意:两个user-server(用户服务)的服务名要一样,ip和端口不一样),在注册中心的服务通信地址清单中user-server(用户服务)这个服务下面会挂载两个通信地址 。 order-server(订单服务)会定时把服务通信地址清单拉取到本地进行缓存, 那么当order-server(订单服务)在向user-server(用户服务)发起调用时,需要指定服务名为 user-server(用户服务);那么这个时候,ribbon会根据user-server(用户服务)这个服务名找到两个order-server的通信地址 , 然后ribbon会按照负载均衡算法(默认轮询)选择其中的某一个通信地址,发起http请求实现服务的调用,如下图:

在这里插入图片描述
在理解了Ribbon工作机制之后,我们就来编码实战上图描述的场景。

2.提供者user-server(用户服务)集群

2.1.服务集群方案

使用SpringBoot多环境配置方式集群,一个配置文件配置多个order-server环境 ,需要注意的是集群中的多个服务名(spring.application.name)应该一样,我们把相同的东西提取到最上面,不同的东西配置在各自的环境中

2.2.用户服务集群配置

修改 application.yml 如下:

#注册到EurekaServer
eureka:
  client:
    serviceUrl:
      defaultZone: http://peer1:1010/eureka/,http://peer2:1011/eureka/,http://peer3:1012/eureka/
  #使用ip地址进行注册
  instance:
    prefer-ip-address: true
spring:
  application:
    name: user-server  #服务名都叫user-server
  profiles:
    active: user-server1
---
server:
  port: 1020
eureka:
  instance:
    instance-id: user-server:1020
spring:
  profiles: user-server1
---
server:
  port: 1021
eureka:
  instance:
    instance-id: user-server:1021
spring:
  profiles: user-server2


用户服务集群配置成功,启动方式同注册中心集群一样。需要配置服务运行多实例启动,启动时需要注意修改spring.profiles.active的值来切换不同的实例。

2.3.修改Controller

为了后续测试的时候方便区分不同的用户服务实例,这里我们在Controller中读取应用的端口随User返回,在启动不同的用户服务实例的时候端口是不同的,修改后的代码如下:

//用户服务:暴露接口给订单访问
@RestController
public class UserController {

	//加载端口
    @Value("${server.port}")
    private int port;

    //订单服务来调用这个方法      http://localhost:1020/user/10
    // @GetMapping(value = "/user/{id}" )
    @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    public User getById(@PathVariable("id")Long id){
        //根据id去数据库查询User
        System.out.println(port);
        return  new User(id,"zs:"+id,"我是zs,port:"+port);	//端口随User返回
    }
}


3.消费者Order-server集成Ribbon

Ribbon集成官方文档:https://cloud.spring.io/spring-cloud-static/Greenwich.SR5/multi/multi_spring-cloud-ribbon.html#netflix-ribbon-starter

修改springcloud-order-server-1030工程,集成Ribbon

3.1.导入依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
3.2.开启负载均衡

修改RestTemplate的Bean的定义方法,加上Ribbon的负载均衡注解@LoadBalanced赋予RestTemplate有负债均衡的能力。

/**
 * 订单的启动类
 */
@SpringBootApplication
@EnableEurekaClient
public class OrderServerApplication1030
{

    //配置一个RestTemplate ,Spring封装的一个机遇Restful风格的http客户端 工具
    //@LoadBalanced :让RestTemplate有负载均衡的功能
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
    //省略...
3.3.修改Controller调用方式

在之前的案例中,我们调用用户服务是通过用户服务的主机加上端口“localhost:1020”的调用方式,现在我们把 “localhost:1020” 修改为 用户服务的服务名 。底层会通过服务发现的方式使用Ribbin进行负载均衡调用。

@RestController
public class OrderController {

    //需要配置成Bean
    @Autowired
    private RestTemplate  restTemplate ;

    //浏览器调用该方法
    @RequestMapping(value = "/order/{id}",method = RequestMethod.GET)
    public User getById(@PathVariable("id")Long id){
        //发送http请求调用 user的服务,获取user对象 : RestTemplate
        //user的ip,user的端口,user的Controller路径
        //String url = "http://localhost:1020/user/"+id;
        String url = "http://user-server/user/"+id;

        //发送http请求
        return restTemplate.getForObject(url, User.class);

    }
}
3.4.测试Ribbon

分别启动EurekaServer注册中心 ,启动两个UserServer用户服务,启动OrderServer订单消费者服务,浏览器访问订单服务:http://localhost:1030/order/1 ,发送多次请求。在这里插入图片描述
观察响应的结果中的端口变化 - 端口会交替出现1020,,1021我们可以推断出Ribbon默认使用的是轮询策略。

4.负载均衡算法

4.1.Ribbon内置算法

Ribbon内置7种负载均衡算法,每种算法对应了一个算法类如下:

内置负载均衡规则类规则描述
RoundRobinRule(默认)简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。
AvailabilityFilteringRule对以下两种服务器进行忽略:(1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。可以通过修改配置loadbalancer..connectionFailureCountThreshold来修改连接失败多少次之后被设置为短路状态。默认是3次。(2)并发数过高的服务器。并发连接数的上线,可以由客户端的..ActiveConnectionsLimit属性进行配置。
WeightedResponseTimeRule为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。
BestAvailableRule忽略哪些短路的服务器,并选择并发数较低的服务器。
RandomRule随机选择一个可用的服务器。
Retry重试机制的选择逻辑
4.2.配置负载均衡算法

Ribbon可以进行全局负载均衡算法配置,也可以针对于具体的服务做不同的算法配置。同时可以使用注解方式和yml配置方式来实现上面两种情况。

1.注解全局配置

随机算法的效果最好演示,我们把负载均衡算法修改成随机算法,只需要RandomRule配置成Bean即可,修改主配置类如下:

/**
 * 订单的启动类
 */
@SpringBootApplication
@EnableEurekaClient
public class OrderServerApplication1030
{

    //配置一个RestTemplate ,Spring封装的一个机遇Restful风格的http客户端 工具
    //@LoadBalanced :让RestTemplate有负载均衡的功能
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    //负载均衡算法
    @Bean
    public RandomRule randomRule(){
        return new RandomRule();
    }
    //省略...

测试
重启订单服务,访问http://localhost:1030/order/1 ,发送多次请求应该可以看到结果中的端口随机变动。

2.配置具体服务的负载均衡

参照官方文档:https://cloud.spring.io/spring-cloud-static/Greenwich.SR5/multi/multi_spring-cloud-ribbon.html#_customizing_the_ribbon_client

如果要针对某一服务配置负载均衡算法可以通过@RibbonClient注解来实现。
先来定义一个注解,用来排除配置类不被扫描到(后面有解释):

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NoScan {
}

然后定义一个配置类,在配置类中定义随机算法策略:

@Configuration
@NoScan //这是一个空标签,是用来防止@SpringBootApplication 扫描到该类
public class RibbonConfig {

    @Bean
    public IRule randomRule(){
        return new RandomRule();
    }
}

提示:需要注意的是这个类我们是要交给RibbonClient作为配置,而不应该被主配置类上的@SpringBootApplication(这个标签里面有个@ComponentScan)所扫描到,不然会不起作用(官方文档上有明确的解释),这里又两种方法可以不让@SpringBootApplication扫描到,1是调整 RibbonConfig 所在包的位置 (@MapperScan扫描当前包及其子包), 2是通过@ComponentScan排除注解的方式,所以我们在配置类上贴了一个注解@NoScan ,后面我们需要根据这个注解排除配置不被扫描。

主配置类通过@RibbonClient指定服务的负载均衡配置,同时排除@NoScan 注解不被扫描

/**
 * 订单的启动类
 */
@SpringBootApplication
//排除 NoScan标签所在的类
@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION,value = NoScan.class))
@EnableEurekaClient
@RibbonClient(value = "user-server",configuration = RibbonConfig.class)
public class OrderServerApplication1030
{

    //配置一个RestTemplate ,Spring封装的一个机遇Restful风格的http客户端 工具
    //@LoadBalanced :让RestTemplate有负载均衡的功能
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    //负载均衡算法
//    @Bean
//    public RandomRule randomRule(){
//        return new RandomRule();
//    }


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

除了 @RibbonClient 注解以外还可以通过@RibbonClients来对多个服务进行策略配置

@RibbonClients({
	@RibbonClient(value = "服务名",configuration = RibbonConfig.class),
	@RibbonClient(value = "服务名",configuration = RibbonConfig.class)
})
3.yml方式配置负载均衡算法

配置全局Ribbon算法

ribbon:
   NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

配置某个服务的Ribbon算法

user-server:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
4.做个总结

上面我们介绍了通过注解方式进行负载均衡策略全局配置和针对某个服务的负载均衡配置,也介绍了通过yml方式配置,我们可以根据项目情况选择其中一种配置方式即可。

5.Ribbon调优配置

5.1.超时配置

使用Ribbon进行服务通信时为了防止网络波动造成服务调用超时,我们可以针对Ribbon配置超时时间以及重试机制

ribbon:
  ReadTimeout: 3000					#读取超时时间
  ConnectTimeout: 3000				#链接超时时间
  MaxAutoRetries: 1 				#重试机制:同一台实例最大重试次数
  MaxAutoRetriesNextServer: 1 		#重试负载均衡其他的实例最大重试次数
  OkToRetryOnAllOperations: false  	#是否所有操作都重试,因为针对post请求如果没做幂等处理可能会造成数据多次添加/修改

当然也可以针对具体的服务进行超时配置:如"<服务名>.ribbon…"

5.2.饥饿加载

我们在启动服务使用Ribbon发起服务调用的时候往往会出现找不到目标服务的情况,这是因为Ribbon在进行客户端负载均衡的时候并不是启动时就创建好的,而是在实际请求的时候才会去创建,所以往往我们在发起第一次调用的时候会出现超时导致服务调用失败,我们可以通过设置Ribbon的饥饿加载来改善此情况,即在服务启动时就把Ribbon相关内容创建好。

ribbon:
  eager-load:
    enabled: true #开启饥饿加载
    clients: user-server #针对于哪些服务需要饥饿加载

6.做个小结

Ribbon的使用相对比较简单,配合RestTemplate使用注解@LoadBalanced即可完成负载均衡配置,但是再我们的订单服务Controller中向用户服务发起请求的代码就显得不简单了。我们需要手动去拼接目标服务的URL,以及参数,可能参数比较简单的时候你没什么感觉,当地址比较复杂,参数比较多的时候,拼接URL就会得特别麻烦,而且显得好傻,在下一章节我们会学习另外一个客户端负载均衡Feign,它在Ribbon的基础上进行了封装,让服务的调用方式显得更简答和高级。

  • 37
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
### 回答1: ork.cloud:spring-cloud-starter-openfeign:jar是一个基于Spring Cloud的开源库,用于化微服务架构中服务之间的调用和通信。 OpenFeign是一个声明式的Web服务客户,它化了编写HTTP请求的代码,使得服务间调用更加单和高效。它是Spring Cloud提供的一个集成了Ribbon和Hystrix的库,可以方便地与其他微服务组件集成使用。 使用OpenFeign,我们可以通过编写接口的方式来定义服务间的调用,而不需要关注底层的HTTP请求。通过注解配置,OpenFeign会自动根据接口定义生成对应的代理类,并且提供了负载均衡、断路器等功能,方便处理高并发和服务故障的情况。 在微服务架构中,服务之间的调用是非常频繁的,而且随着微服务的增多,手动编写HTTP请求的代码会变得非常繁琐和容易出错。使用OpenFeign可以大大化服务之间的调用流程,提高开发效率和代码质量。 总结来说,ork.cloud:spring-cloud-starter-openfeign:jar是一个方便而强大的库,可以帮助我们化微服务架构中服务之间的调用和通信,并且提供了负载均衡和断路器等功能,能够提高系统的可靠性和性能。 ### 回答2: ork.cloud:spring-cloud-starter-openfeign:jar是一个基于Spring Cloud的开源项目,它提供了一种方便的编写和调用RESTful服务的方式。Feign是一个声明式的Web服务客户,它可以化HTTP请求的处理和封装,使得开发者可以更加专注于业务逻辑的编写。 使用Spring Cloud Starter OpenFeign可以快速地编写和调用其他微服务。它通过注解的方式将HTTP请求映射到对应的方法上,自动进行了服务的发现和负载均衡。 Feign支持多种请求方式,包括GET、POST、PUT、DELETE等,还可以使用@PathVariable、@RequestParam等注解处理路径参数和查询参数。Feign还支持对请求体进行处理,可以将请求体转换成Java对象,方便业务逻辑的处理。 在使用Feign时,不需要手动编写HTTP请求的代码,只需要定义一个接口并使用Feign的注解进行标记即可。Feign会根据注解生成代理对象来完成请求的发送和接收。这样可以大大化开发的工作量,并且使得代码更加清晰易读。 Spring Cloud Starter OpenFeign还集成了Ribbon和Hystrix,这使得我们在使用Feign时可以实现负载均衡和熔断的功能。即使请求的目标服务发生宕机或故障,也能够保证系统的高可用性和稳定性。 总之,Spring Cloud Starter OpenFeign是一个非常实用和方便的工具,可以化微服务架构下的服务调用,并提供了负载均衡和熔断等功能。它的使用可以加快开发速度,提高系统的可靠性和稳定性。 ### 回答3: spring-cloud-starter-openfeign是一个开源的Spring Cloud组件,用于化在微服务架构中进行远程服务调用的过程。它基于Netflix的Feign库进行开发,提供了一种声明式的、基于接口的远程服务调用方式,可以方便地实现服务之间的通信和数据交互。 ork.cloud:spring-cloud-starter-openfeign:jar是spring-cloud-starter-openfeign组件的一个特定版本的jar包。在使用Spring Boot构建的项目中,可以通过引入这个jar包来集成并使用spring-cloud-starter-openfeign组件,从而化远程服务调用的代码编写和配置。 使用spring-cloud-starter-openfeign,我们只需要定义一个接口,通过注解的方式声明远程服务的地址和调用方法,然后在需要调用远程服务的地方直接调用这个接口的方法即可。Spring Cloud会根据注解信息自动进行服务发现和负载均衡,将我们的调用请求转发到对应的服务实例上。 该jar包中除了包含spring-cloud-starter-openfeign的核心功能外,还可能包含一些额外的依赖库或工具,以及特定版本的相关代码和配置文件。通过引入这个jar包,我们可以一键集成和启用spring-cloud-starter-openfeign组件,省去了手动添加依赖和配置的步骤,能够更快速地搭建起微服务架构中的服务调用机制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨家巨子@俏如来

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值