Spring Cloud —— 负载均衡与 Ribbon 应用

引言

本篇博客简单介绍微服务负载均衡的概念,并通过 IDEA 多端口启动应用的方式,模拟多个应用实例,使用自定义和 Ribbon 两种方式实现基本的负载均衡策略。

微服务代码以《Spring Cloud Alibaba——Nacos实现服务治理》为基础。

一、什么是负载均衡

负载指的是系统接收请求的压力,通常来讲,单体应用如果接收的请求量过多,会对应用本身造成一定的并发困扰,导致逻辑出错,甚至是服务瘫痪。

为了解决单个应用访问量过大的情况,人们很自然的想到将一个单体应用克隆多份,来分摊请求量,均衡负载。

负载均衡就是将负载(工作任务、访问量)进行分摊到多个操作单元(服务器、组件)上执行的一套技术。

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

1、服务端负载均衡指的是分摊工作发生在服务提供者一方,比如常见的 Nginx 。

2、客户端负载均衡则恰好相反,它指的是分摊工作发生在服务请求的一方,即在发送请求之前就已经选好了由具体的哪一个实例处理请求。如下图所示:

一般在微服务中,都是使用客户端负载均衡

二、IDEA 中模拟多个微服务实例

使用 idea 可以轻松的为一个 spring boot 服务创建多个微服务实例。以《Spring Cloud Alibaba——Nacos实现服务治理》的代码用例为例,这里简单回顾一下 Demo 用例。

我们创建了一个电商系统,有三个微服务:shop-user 用户微服务、shop-product 商品微服务、shop-order 订单微服务,我们使用 Nacos 实现了服务的注册发现,并实现了完整的用户下单——>查询商品——>返回订单的微服务调用逻辑,如下图所示:

但上述案例只涉及到了一个订单微服务实例对应另一个商品微服务实例,并没有任何负载均衡的效果,为了演示负载均衡,我们可以通过 idea 将shop-product 微服务启动多个实例。

方法是,在启动项中添加多个:

配置好第二个商品微服务实例之后,我们启动 ProductApplication 和 ProductApplication2,可以在 Nacos 中看到注册的商品服务实例有 2 个(关于Nacos 的相关知识参考《Spring Cloud Alibaba——Nacos实现服务治理》):

三、自定义负载均衡

最简单的负载均衡机制就是通过随机数,根据服务提供者(商品服务)的实例数量,来随机生成服务序号,从而确定访问的实例。

我们在订单微服务中加入随机数代码:

以下是完整代码: 

@Slf4j
@RestController
@RequestMapping("/order")
public class OrderController {@Autowiredprivate RestTemplate restTemplate;@Autowiredprivate DiscoveryClient discoveryClient;@Autowiredprivate OrderService orderService;/**** 下单* @param pid* @return*/@GetMapping("/prod/{pid}")public Order order(@PathVariable("pid") Integer pid) {log.info("接收到{}号商品的下单请求,准备调用商品微服务", pid);// 获取服务实例列表List<ServiceInstance> serviceList = discoveryClient.getInstances("service-product");// 生成随机下标 0 1int index = new Random().nextInt(serviceList.size());// 获取实例对象ServiceInstance productService = serviceList.get(index);// 调用商品微服务,查询商品信息Product prod = restTemplate.getForObject("http://" + productService.getHost() + ":" + productService.getPort() + "/product/" + pid, Product.class);log.info("查询到{}号商品信息,内容是:{}", pid, JSON.toJSONString(prod));// 下单(即创建订单并保存)Order order = new Order();order.setUid(1);order.setUsername("测试用户");order.setPid(pid);order.setPname(prod.getPname());order.setPprice(prod.getPprice());order.setNumber(1);// 订单入库orderService.createOrder(order);log.info("创建订单成功,订单信息为:{}", JSON.toJSONString(order));return order;}
}

启动 OrderApplication ,并调用下单接口,观察每次请求时,商品微服务后台日志的打印情况:

总共请求了四次,商品实例1调用了3次,商品实例2调用了1次,随机数负载均衡成功。

四、Ribbon 实现负载均衡

Ribbon 是 Spring Cloud 的一个组件,它可以让我们使用一个注解就能轻松搞定负载均衡。Ribbon 的默认负载均衡策略是轮询。

整合方法只需两步:

1、在 RestTemplate 注入的时候,添加 @LoadBalanced 注解:

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

2、修改服务调用的方法,以服务名称直接代替 ip 和 端口号:

@GetMapping("/prod/{pid}")
public Order order(@PathVariable("pid") Integer pid) {log.info("接收到{}号商品的下单请求,准备调用商品微服务", pid);// 调用商品微服务,查询商品信息Product prod = restTemplate.getForObject("http://service-product/product/" + pid, Product.class);log.info("查询到{}号商品信息,内容是:{}", pid, JSON.toJSONString(prod));...return ...;
}

(演示效果略)

Ribbon 的常用负载均衡策略有三个:

RoundRobinRule轮询选择 service instance轮询 index,选择索引对应的服务实例
RandomRule随机选择一个 instance

在 index 上随机,选择对应位置的服务实例

BestAvailableRule选择一个最小的并发请求的 instance

考察每个实例,如果实例被 tripped 了,则忽略。再选择其中 ActiveRequestsCount最小的实例

修改 Ribbon 的负载均衡策略非常简单,只需要在配置文件中指定即可:

# 调用的服务名称
service-product:ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

演示效果同第三节。

总结

项目的代码以《Spring Cloud Alibaba——Nacos实现服务治理》基础,可能缺少一些中间环境,建议结合阅读。

负载均衡的作用是分摊流量,避免某一个服务因为请求压力而瘫痪。

负载均衡的模式一般有两种,客户端负载均衡和服务端负载均衡。一般在微服务调用中,都是使用客户端负载均衡。

Ribbon是实现负载均衡的重要组件,它的负载均衡策略主要有三个:轮询(默认)、随机、最小并发。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/558684.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring —— 容器内部逻辑

引言 上一篇关于IoC容器的详解《Spring —— IoC 容器详解》真是工程浩大&#xff0c;可以说Spring官网对核心中的核心IOC容器做了非常全面的使用说明&#xff0c;包括在《Spring揭秘》中让我一直没有成功的Method Injection&#xff0c;官网也解决了我的疑惑&#xff0c;并最…

2020 年度总结

2020年给我的感觉是短平快的一年。 由于年初的新冠肺炎疫情&#xff0c;我大半年都呆在北京的破旧出租屋里写代码。整个春天和夏天&#xff0c;平平无奇。 2月1日返京&#xff0c;居家办公&#xff0c;夜跑。8月复工&#xff0c;疯狂爆痘、烂脸&#xff0c;月末落户天津。9月…

JDBC——概述与JDBC的使用

引言 一直希望深入学习一下数据库持久化技术&#xff0c;接触过Hibernate、Mybatis&#xff0c;也使用过Spring事务管理来控制回滚操作&#xff0c;但是越发觉得底层知识有一定的知识盲区和空洞。 很多ORM框架都是基于JDBC规范来进行构建的&#xff0c;因此&#xff0c;学习J…

JDBC——编程式事务的实现逻辑

引言 数据库事务的概念和基础&#xff0c;总结在《MySQL 基础 ————事务与隔离级别总结》。 本篇博客通过“JDBC 纯编码”方式实现事务控制&#xff0c;完成一个 A 给 B 转账的小功能&#xff0c;在进一步熟练JDBC的编程流程的同时&#xff0c;重点关注 Java 语言如何操作…

排序算法——插入排序

一、算法思想 给定一个无序数列&#xff0c;模拟一个指针从第0位开始向后&#xff0c;始终保持当前位置左边的数列是有序的。 指针位置上的元素依次与前面的元素比较&#xff0c;当遇到小于自己的数或右边已经没有元素时&#xff0c;都停止比较&#xff0c;开始下一轮。 生活…

Linux 底层原理 —— epoll 与多路复用

引言 epoll 是 Linux 系统下高性能网络服务的必备技术&#xff0c;很多面试中高频出现的 Nginx、Redis 都使用了这一技术&#xff0c;本文总结 linux 多路复用模型的演变过程&#xff0c;看一看epoll 是如何实现高性能的。 一、相关基础知识 1.1 文件描述符 文件描述符&…

异或运算的应用

一、基础知识 异或运算&#xff0c;相异为1。 异或运算是一种常用的位运算&#xff0c;在算法题中&#xff0c;对于避免额外的空间复杂度有独特的用处。 异或运算也被称为“无进位相加”&#xff0c;它具有以下特性&#xff1a; 特性1&#xff1a;0 ^ N N 特性2&#xff1a…

单向队列、双端队列、栈的模型实现

引言 自己实现简单的队列、栈的逻辑结构。 队列都包含头和尾两个指针&#xff0c;简单的单向队列只能在一端&#xff08;如&#xff1a;head端&#xff09;入列&#xff0c;在另一端&#xff08;如&#xff1a;tail 端&#xff09;出列&#xff1b;双端队列可以在 head 进出&…

递归算法及其时间复杂度分析

引言 “递归” 一词是比较专业的计算机术语&#xff0c;在现实生活中&#xff0c;有一个更可爱的词——“套娃”。如果把“递归算法”叫做“套娃算法”&#xff0c;或许可以减少一些恐惧程度。 套娃是有限的&#xff0c;同样&#xff0c;递归也是有限的&#xff0c;这和我们经…

算法设计中的基础常用代码

引言 本篇博客旨在记录一些基础算法知识的常见组合用法&#xff0c;以及何时使用&#xff0c;需要注意的问题等&#xff0c;长期更新。 为什么要这样总结呢&#xff1f;难道掌握了位运算、常用算法工具API的定义还不够吗&#xff1f; 这是因为某些知识比如 &、 |、 ~、 …

Redis —— 常用命令一览

引言 参考《菜鸟教程 Redis 常用命令》&#xff0c;其中红色为极其重要&#xff0c;蓝色为重要。 一、总览 二、key相关命令 三、String 相关命令 四、Hash 相关命令 五、List 相关命令 六、Set 相关命令 七、ZSet 相关命令

Redis 实用技术——消息发布和订阅

引言 发布订阅模型是redis的重要功能&#xff0c;它可以像网站动态一样&#xff0c;将消息发送到多个订阅者的主页里。 一、常用命令 二、消息格式 消息是一个有三个元素的多块响应&#xff1a; 如上图&#xff0c;发布者向 mysub 频道发送了一条消息&#xff0c;redis会返回…

Redis 实用技术——事务

引言 redis的事务不像关系型数据库的事务那样完整。 “快”是redis的特征&#xff0c;在事务管理的过程中&#xff0c;使用muti命令开启事务块&#xff0c;当输入多条命令后&#xff0c;再使用exec命令执行事务块中的全部命令。 Redis事务可以保证两件事&#xff1a; 1、隔…

排序算法——归并排序的相关问题

一、小和问题 问题描述&#xff0c;给定一个数组&#xff0c;如[1, 3, 2, 6, 5]&#xff0c;计算每个数左边小于自己的所有数的和&#xff0c;并累加。例如&#xff1a; 1左边没有数 3左边有一个小于自己的数 1 2左边有一个小于自己的数 1 6左边有三个小于自己的数 1 3 2 6…

经典数据结构——堆的实现

一、完全二叉树 堆是一种完全二叉树&#xff0c;什么是完全二叉树&#xff1f; 简单的说&#xff0c;一棵满二叉树表示的是所有节点全部饱和&#xff0c;最后一层全部占满&#xff1a; 而完全二叉树指的是满二叉树的最后一层&#xff0c;所有叶子节点都从左往顺序排满&#x…

排序算法 —— 堆排序

引言 此文基于《经典数据结构——堆的实现》中堆结构&#xff0c;实现一个以堆处理排序的算法。 一、算法思想 基于堆结构的堆排序的算法思想非常简单&#xff0c;循环获取大根堆中的最大值&#xff08;0位置的根节点&#xff09;放到堆的末尾&#xff0c;直到将堆拿空。 由…

经典数据结构——前缀树

引言 前缀树——trie /ˈtraɪ//树&#xff0c;也叫作“单词查找树”、“字典树”。 它属于多叉树结构&#xff0c;典型应用场景是统计、保存大量的字符串&#xff0c;经常被搜索引擎系统用于文本词频统计。它的优点是利用字符串的公共前缀来减少查找时间&#xff0c;最大限度…

排序算法 —— 计数排序

引言 计数排序是桶排序思想的一种具体实现&#xff0c;针对一些具有特殊限制的样本数据&#xff0c;如公司员工年龄&#xff0c;那么样本数据本身就一定在0~200之间&#xff0c;针对这样的数据&#xff0c;使用从0到200 的桶数组&#xff0c;桶的位置已经是有序的&#xff0c;…

Java多线程 —— 线程状态迁移

引言 线程状态迁移&#xff0c;又常被称作线程的生命周期&#xff0c;指的是线程从创建到终结需要经历哪些状态&#xff0c;什么情况下会出现哪些状态。 线程的状态直接关系着并发编程的各种问题&#xff0c;本文就线程的状态迁移做一初步探讨&#xff0c;并总结在何种情况下…

Java中的Unsafe

Java和C语言的一个重要区别就是Java中我们无法直接操作一块内存区域&#xff0c;不能像C中那样可以自己申请内存和释放内存。Java中的Unsafe类为我们提供了类似C手动管理内存的能力。 Unsafe类&#xff0c;全限定名是sun.misc.Unsafe&#xff0c;从名字中我们可以看出来这个类对…