Spring Cloud负载均衡及远程调用实现详解

 更新时间:2020年08月21日 09:14:07   作者:编了个程  
这篇文章主要介绍了Spring Cloud负载均衡及远程调用实现详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

负载均衡

使用微服务后,为了能够承担高并发的压力,同一个服务可能会启动多个实例。这时候消费者就需要负载均衡,把请求分散到各个实例。负载均衡主要有两种设计:

服务端负载均衡客户端负载均衡

对于传统的分布式服务来说,大多使用服务端负载均衡。一般会使用Nginx或者ELB等工具作为负载均衡器,如下图:


传统负载均衡

而在Spring Cloud中,使用的是「客户端负载均衡」的方式,使用「Ribbon」组件来实现客户端的负载均衡。只要引入了微服务注册中心依赖,就会自动引入Ribbon依赖。客户端负载均衡原理如下图:

客户端负载均衡

Ribbon的原理

Ribbon利用了RestTemplate的拦截器(接口是ClientHttpRequestInterceptor)机制,在拦截器中实现的负载均衡。负载均衡的基本实现就是利用从「服务注册中心」获取可用的服务地址列表,然后通过一定算法负载,决定使用哪一个服务地址来进行HTTP调用。

详情可以查看LoadBalancerInterceptor这个类,位于org.springframework.cloud.client.loadbalancer包下。

使用Ribbon

首先定义一下生产者「service-user」,我这里使用容器启动了多个生产者实例,每个实例具有不同的id,我的示例代码里面启动了两个实例:

service-user-1
service-user-2

代码:

@RestController
@RequestMapping
public class HelloController {

  @Value("${spring.cloud.consul.discovery.instanceId}")
  private String instanceId;

  @GetMapping("hello")
  public String hello() {
    return String.format("hello, this is %s", instanceId);
  }
}

然后对于消费者「service-order」,可以使用Java声明式注解的方式来使用Ribbon,只需要在消费者给RestTemplate类型的Bean配上一个@LoadBalanced就可以了。然后再配置一下负载均衡策略:

@Configuration
public class RibbonConfig {

  @Bean
  @LoadBalanced
  public RestTemplate ribbonRestTemplate(){
    return new RestTemplate();
  }

  @Bean
  public IRule ribbonRule() {
    return new RandomRule(); // 随机负载均衡
  }
}

然后就可以直接使用自动注入的RestTemplate类型的Bean了:

@RestController
@RequestMapping
public class HelloController {

  @Autowired
  RestTemplate restTemplate;

  @GetMapping("/ribbon/service-user")
  public String ribbonService(){
    return restTemplate.getForObject("http://service-user/hello", String.class);
  }
}

这个时候访问消费者的/ribbon/service-user,刷新几次,就会看到下面两个随机的响应:

hello, this is service-user-2
hello, this is service-user-1

负载均衡策略

查看IRule接口的实现类,可以看到Ribbon的所有负载均衡策略,查看各实现类顶部的注释可以看到它的具体策略:


负载均衡器

  • RandomRule:随机选择;
  • RoundRobinRule:轮询;
  • WeightedResponseTimeRule:根据每个服务的响应时间设置权重,响应时间越长,所占权重越少;
  • AvailabilityFilteringRule:过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值);
  • ZoneAvoidanceRule:使用CompositePredicate根据区域和可用性过滤服务器的规则;
  • BestAvailableRule:选择一个最小的并发请求的server;
  • RetryRule:在现有的策略基础上,添加重试机制,因为IRule支持「级联」。

远程调用

Spring Cloud提供了OpenFeign组件(以前叫Feign)来进行远程的HTTP调用。它是对RestTemplate的一个封装。

Feign是一个声明式Web Service客户端。使用Feign能让编写Web Service客户端更加简单。Spring Cloud对Feign进行了封装,使其支持了Spring MVC标准注解和HttpMessageConverters。Feign可以与微服务注册中心和Ribbon组合使用以支持负载均衡。

使用OpenFeign

第一步,引入依赖:

implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'

第二步,启动配置,在启动类上添加@EnableFeignClients注解:

@SpringBootApplicationbr/>@EnableFeignClients
public class ServiceOrderApplication {
public static void main(String[] args) {
  SpringApplication.run(ServiceOrderApplication.class, args);
}
}

第三步:声明调用接口,我这里案例是service-order调用service-user的/hello接口,这里的注解就跟Spring MVC的注解一致:

注意Feign在做POST请求的时候有一个小坑,详情参考:SpringCloud Feign Post表单请求。

@FeignClient("service-user")
public interface UserClient {
  @GetMapping("hello")
  String getUserHello();
}

第四步:使用,注解使用@Autowired注解注入就可以了:

@RestController
@RequestMapping
public class HelloController {

  @Autowired
  UserClient userClient;

  @GetMapping("hello")
  public String hello() {
    return "hello, this is order service";
  }

  @GetMapping("userHello")
  public String user() {
    return userClient.getUserHello() + ", this is order-service";
  }
}

是不是看起来非常简单?

OpenFeign集成Ribbon

前面我们提到,OpenFeign底层是对RestTemplate的一个封装,而Ribbon是通过给RestTemplate添加过滤器来实现的,所以OpenFeign天生就自动集成了Ribbon,我们不需要任何额外的配置。

在上述代码中,启动后,可以访问service-order的/userHello端口,不断刷新,发现已经实现了负载均衡。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 图解红黑树及Java进行红黑二叉树遍历的方法

    图解红黑树及Java进行红黑二叉树遍历的方法

    红黑树问题是各大计算机考研命题以及面试算法题目中的热门,接下来我们为大家图解红黑树及Java进行红黑二叉树遍历的方法,需要的朋友可以参考下
    2016-05-05
  • Java实现利用广度优先遍历(BFS)计算最短路径的方法

    Java实现利用广度优先遍历(BFS)计算最短路径的方法

    这篇文章主要介绍了Java实现利用广度优先遍历(BFS)计算最短路径的方法,实例分析了广度优先遍历算法的原理与使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-04-04
  • 一篇文章带你了解SpringBoot Web开发

    一篇文章带你了解SpringBoot Web开发

    这篇文章主要介绍了使用Spring Boot搭建Java web项目及开发过程,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-08-08
  • Java中String类(字符串操作)的10个常见问题和解决方法

    Java中String类(字符串操作)的10个常见问题和解决方法

    这篇文章主要介绍了Java中String类(字符串)操作的10个常见问题,需要的朋友可以参考下
    2014-04-04
  • Spring框架基于注解开发CRUD详解

    Spring框架基于注解开发CRUD详解

    这篇文章主要为大家详细介绍了Spring框架基于注解开发CRUD,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • MyBatis动态SQL之<choose><when><otherwise>标签的使用

    MyBatis动态SQL之<choose><when><otherwise>标签的使用

    MyBatis中动态语句choose-when-otherwise 类似于Java中的switch-case-default语句,本文就来介绍一下MyBatis动态SQL之<choose><when><otherwise>标签的使用,感兴趣的可以了解一下
    2023-09-09
  • java实现文件切片上传百度云+断点续传的方法

    java实现文件切片上传百度云+断点续传的方法

    文件续传在很多地方都可以用的到,本文主要介绍了java实现文件切片上传百度云+断点续传的方法, 文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-12-12
  • SpringBoot实现热部署详解

    SpringBoot实现热部署详解

    SpringBoot热部署是一种开发时极为有用的功能,它能够让开发人员在代码修改后无需手动重启应用程序就能立即看到变化的效果,所以我本文就给打击介绍一下为什么要使用热部署以及实现热部署的方式,需要的朋友可以参考下
    2023-07-07
  • Springboot工具类StringUtils使用教程

    Springboot工具类StringUtils使用教程

    这篇文章主要介绍了Springboot内置的工具类之StringUtils的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习吧
    2022-12-12
  • Java日常练习题,每天进步一点点(7)

    Java日常练习题,每天进步一点点(7)

    下面小编就为大家带来一篇Java基础的几道练习题(分享)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧,希望可以帮到你
    2021-07-07

最新评论