目录
[Spring Cloud LoadBalancer](#Spring Cloud LoadBalancer)
[LoadBalancer 原理](#LoadBalancer 原理)
负载均衡介绍
问题引出
上篇文章中,实现远程调用的代码如下:

根据应用名称获取到了服务实例列表,从列表中选择了一个服务实例。
但如果一个服务对应多个实例呢?流量在这些实例中是如何分配?
现象观察:
在 Services 中先启动三个服务

然后再多启动两个 product-service 实例




此时观察 eureka,可用看到 product-service 下有三个实例。

通过日志发现,发出了多次访问,但都到了同一台机器上。
我们希望的是,启动多个实例之后,请求可用被分担到其他机器上。
解决:
对 order-service 中的 service 再进行修改:

重启 order-service,通过日志可以观察,请求被均衡的分配在了不同的实例上,这就是负载均衡。

什么是负载均衡
负载均衡(Load Balance),是高并发,高可用系统必不可少的关键组件。
当服务流浪增大时候,会采用增加机器的方式进行扩容。负载均衡就是使用多个机器或者其他资源中,按照一定的规则合理分配负载。
负载均衡的一些实现
上面的案例中,我们简单对实例进行了轮询。在真实的开发环境中,会更加复杂。比如根据机器的配置进行负载分配...
服务多机部署的时候,开发人员都需要考虑负载均衡的实现,所以也出现了一些负载均衡器,来帮助我们实现负载均衡。
负载均衡器分为:服务端 负载均衡和客户端负载均衡。
服务端负载均衡
在服务端进行负载均衡的算法分配。
比较有名的是 Nginx,请求先到达 Nginx 负载均衡器,然后通过负载均衡算法,在多个服务器之间选择一个进行访问。

客户端负载均衡
在客户端进行负载均衡的算法。
把负载均衡的功能,以库的方式集成到客户端,而不是由一台指定的负载均衡设备集中提供。
比如 Spring Cloud 的 Ribbon,请求发送到客户端,客户端从注册中心获取服务列表,在发送请求前,通过负载均衡算法选择一个服务器,然后进行访问。
Ribbon 是早期 Spring Cloud 的默认实现,由于不维护了,所以最新版本的 Spring Cloud 负载均衡集成的是 Spring Cloud LoadBalancer

客户端和服务端这两种负载均衡器,最大的区别在于服务清单所存储的位置。
Spring Cloud LoadBalancer
使用
- 给 RestTemplate 这个 Bean 添加 @LoadBalanced 注解

- 修改 IP 端口号为服务名称

这时候观察日志,就会发现请求已经被分配到 3 个实例上了。
负载均衡策略
负载均衡是一种思想。Spring Cloud Load Balancer 仅支持两种负载均衡策略:轮询策略和随机策略。
-
轮询:就是指服务器轮流处理用户的请求,这是一种实现最简单,也是最常用的策略。
-
随机:随机选择一个后端服务器来处理新的请求。
自定义负载均衡策略
Spring Cloud LoadBalancer 默认负载均衡策略是轮询策略,实现是 RoundBobinLoadBalancer。
如果要实现随机的负载均衡策略:
根据官网地址:Spring Cloud LoadBalancer :: Spring Cloud Commons

在我们的项目中,实现一个 CustomLoadBalancerConfiguration 类。

我们使用的 RestTemplate 实现的远程调用,则在上面加上 @LoadBalancerClient 注解

看一下 @LoadBalancerClient 注解的属性:name / value 和 configuration


在 RestTemplate 配置

重新部署,实现了随机负载分配~
LoadBalancer 原理
LoadBalancer 的实现,主要是 LoadBalancerInterceptor,这个类会对 RestTemplate 的请求进行拦截,然后从 Eureka 根据服务 id 获取服务列表,然后利用均衡算法,得到真实的服务地址信息,替换服务 id。
源码实现:

在 intercept 方法中,拦截了用户的 HttpRequest
-
request.getURI() 从请求中获取了 URI
-
orginalUri.getHost() 从 uri 中获取到了路径的主机名,也就是服务 id,product-service
-
loadBalancer.execute 根据服务 id 进行负载均衡,并请求处理。
点进行进行追踪:
在 choose 方法中,根据 serviceId 和负载均衡策略,选择处理的服务。

在 choose 中,先获取负载均衡器,然后根据算法,选择一个服务实例

可以再点进去这个 choose 中进行观察

这个接口,就由轮询和随机负载均衡的实现~

服务部署
接下来我们将服务部署到 Linux 系统上
在 Linux 系统中,同样建立数据库。


服务构建打包
采用 Maven 进行打包,需要对三个服务分别进行打包
在子项目中 order-service 和 product-service 中的 pom 文件中进行如下配置

再对 application.yml 进行复制配置:

在 prod 生产环境中,对数据库的密码进行修改。
然后在 application.yml 文件中,让 Maven 仓库进行自动选择:

之后在 Maven 仓库中,选择 prod 环境进行打包


将 jar 包放到云服务器中,直接拖动文件到 xshell 窗口即可。
(第一次上传,需要安装 lrzsz : apt install lrzsz)
启动服务:

在云服务器控制台中,在防火墙设置中,将对应的端口号进行开放。
测试:
访问公网 ip:8080/order/1
远程调用实现成功。