书籍地址: Spring Cloud 微服务架构开发实战
对于大型应用系统来说,负载均衡(Load Balancing,LB) 是一个必须要被解决的问题.
微服务之前,负载均衡方案主要是集中式负载均衡方案, 在服务消费者和服务提供之之间存在一个独立的负载均衡系统.
该负载均衡系统上有所有服务的地址映射表,当服务消费者调用某个目标服务时,先向负载均衡系统发起请求,由负载均衡系统以某种策略(如轮询) 做负载均衡后再将请求转发给目标服务.
但是 该方案,有缺点:
-
单点失败
对于集中式负载均衡解决方案来说,虽然可以尽力提高其可靠性,但单点失败却难以避免,一点负载均衡宕机,则整个应用将无法访问 -
难扩展
-
复杂
4.3.1 什么是客户端负载均衡
在微服务架构中,通常服务提供者是以集群方式提供服务, 对负载均衡要求也很高. 根据负载均衡所在位置的不同, 目前针对微服务架构中负载均衡的解决方案主要有3种:
-
集中式负载均衡方案.
在服务消费者和服务提供者之间有一个独立的负载均衡系统来承担负载均衡功能, 该方案和之前的传统单体架构负载均衡实现原理一致;
-
进程内负载均衡方案.
该方案降幅在均衡处理功能以库的方式整合到服务消费者应用中. 因此也被称为客户端负载均衡
客户端负载均衡方案需要配合服务发现功能, 在服务消费者启动时需要从服务发现服务器中获取所有服务注册信息,并定时同步这些注册信息.
当服务消费者需要访问某个服务时, 内置的负载均衡器就会以某种负载均衡策略选择一个目标服务实例,然后在本地锁缓存的服务注册表信息中查询该目标服务的具体地址,最后向目标服务发起请求.
-
主机独立负载均衡进程方案
该方案是对二种方案的一种折中. 原理类似. 但也有所不同.
不同之处: 是将负载均衡和服务发现功能从服务消费者的进程内移出来,变成同一个主机上的一个独立进程.为该主机上的一个或者多个服务消费者提供负载均衡处理.
第二种负载均衡方案,在Netflix的微服务开源项目中有一子项目Ribbon,该子项目可以和Eureka无缝整合,共同为我们提供客户端负载均衡功能
4.3.2 启用Ribbon
从客户端负载均衡解决方案的原理中可以看到,需要进行修改的是服务消费额方,即实例中的商品微服务,对于服务提供方不需要做任何修改。
1. pom.xml文件修改
只需要加入ribbon的依赖
<!--ribbon-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.1.3.RELEASE</version>
</dependency>
2. 项目启动类中 restTemplate 的修改
//创建一个RestTemplate Bean
@Bean(value = "restTemplate")
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
只需要加上
@LoadBalanced
注解, 就让restTemplate
具备了负载均衡的功能
Ribbon
实现负载均衡的原理可以概括为以下4个步骤:
- Ribbon首先根据其所在Zone优先选择一个负载教少的Eureka服务器.
- 定期从Eureka服务器更新, 并过滤服务实例列表.
- 根据指定的负载均衡策略,从可用的服务实例列表中选择一个.
- 然后使用该地址,通过REST客户端进行服务调用.
默认情况下,客户端负载均衡采用了轮询策略(RoundRobinRule),也就是说Ribbon会交替访问从Eureka中所获取的用户微服务实例.
3. 商品微服务,用户微服务代码修改
为了方便看到Ribbon
让商品微服务具有了负载均衡功能,我们在该项目的UserDto类中和用户微服务项目的UserDto类中添加 用户服务端口,如下
//用户服务端口
private Integer userServicePort;
在用户微服务的UserServiceImpl
类中的load
方法中对查出来的sysUsersList做一个元素属性的添加
userDto.setUserServicePort(serverPort);
4. 测试负载均衡
项目启动步骤如下:
- 先启动服务治理服务器 server-discovery
- 启动商品微服务
- 使用以下方式启动用户微服务
测试负载均衡,我们至少需要两个用户微服务, 你当然可以COPY一份代码,然后修改一下server.port ,然后通过IDEA启动
我们可以将用户打成JAR包,
打包的时候如果您用的是IDEA 记得先讲parent包 install , user-service 使用Lifecycle中的clean和install命令打包
通过以下命令启动用户微服务
第一个用户微服务
java -jar user-service-0.0.1.jar
第二个用户微服务,通过server.port参数指定端口为2110
java -jar user-service-0.0.1.jar --server.port=2110
5. 检查是否启动成功+Postman测试
检查
同样,我们访问 htttp://localhost:8260 此时应该有三个服务注册进来. 分别是用户的两个, 商品的一个
通过Postman 多次(轮询按道理两次即可)访问商品微服务的 http://localhost:2200/comment/2/comments, 能够得到2100,和2200的两个port 响应就说明我们负载均衡测试是成功的.
端口响应
看到这的同学会不会有人问,为什么一个请求是两个不同的端口响应呢?
原因其实很简单,因为我们在代码中,请求用户微服务就是多次. 我的评论数据表里面,评论商品2的用户有多个,因此请求用户微服务就有多次.
结束