Spring Cloud 负载均衡
1. 概念
负责均衡 (Load Balance,简称LB),是高并发、高可用系统必不可少的关键组件。
当服务流量增大时,通常会采用增加机器的方式来进行扩容,负载均衡就是用来在多个机器或者其它资源中按照一定的规则合理分配负载
类似于在公司中,一个团队最开始只有一个人,后来随着工作量的增加,公司又招聘了几个人,就要考虑到负载均衡,如何把工作量均衡的分配到这几个人身上,从而提高整个团队的效率!
2. 分类
负责均衡分为服务端负载均衡和客户端负载均衡:
2.1 服务端负载均衡
在服务端进行负责均衡的算法分配,比较有名的服务端负载均衡器是Nginx,请求先到达Nginx负载均衡器,然后通过负载均衡算法,在多个服务器之间选择一个进行访问:
2.2 客户端负载均衡
在客户端进行负载均衡的算法分配.
把负责均衡的功能以库的方式集成到客户端,而不再是由一台指定的负载均衡设备集中提供
比如Spring Cloud的
Ribbon
,请求发送到客户端,客户端从注册中心(如Eureka)获取服务列表,在发送请求前通过负载均衡算法选择一个服务器,然后进行访问
Ribbon是Spring Cloud早期的默认实现,由于现在已不再维护,最新版本的Spring Cloud负载均衡集成的是由Spring Cloud官方维护的 Spring Cloud LoadBalancer
3. Spring Cloud LoadBalancer
在SpringCloud中,我们使用Spring Cloud LoadBalancer
来实现负载均衡,使用方式如下
给RestTemplate这个Bean添加
@LoadBalanced
注解package com.order.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class BeanConfig { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
修改IP端口号为服务名称(
OrderServiceImpl
)package com.order.service.Impl; import com.order.mapper.OrderMapper; import com.order.model.OrderInfo; import com.order.model.ProductInfo; import com.order.service.OrderService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import java.util.List; @Service public class OrderServiceImpl implements OrderService { @Autowired private OrderMapper orderMapper; @Autowired private DiscoveryClient discoveryClient; @Autowired private RestTemplate restTemplate; @Override public OrderInfo selectOrderById(Integer orderId) { OrderInfo orderInfo = orderMapper.selectOrderById(orderId); // String url = "http://127.0.0.1:9090/product/" + orderInfo.getProductId(); String url = "http://product-service/product/" + orderInfo.getProductId(); ProductInfo productInfo = restTemplate.getForObject(url, ProductInfo.class); orderInfo.setProductInfo(productInfo); return orderInfo; } }
启动多个product-service实例
先复制一份实例:
更改实例名称,并修改选项:
选择
Add VM options
选项:添加
-Dserver.port=自定义端口号
部署好后同时启动多个product-service
实例,并刷新eureka-server
:
可以看到新创建的几个实例都加入了注册中心!
这个时候我们来调用order-service服务,并多次刷新调用,可以看到每个product-service都被均衡的调用到了!
4. 负载均衡策略
负载均衡策略是一种思想,无论是哪种负载均衡器,它们的负载均衡策略都是相似的。Spring Cloud LoadBalancer 仅支持两种负载均衡策略:轮询策略 和 随机策略:
- 轮询(Round Robin):指服务器轮流处理用户的请求,这个一种实现最简单,也最常用的策略
- 随机选择(Random):随机选择一个后端服务器来处理新的请求
Spring Cloud LoadBalancer 默认负载均衡策略是 轮询策略,实现的是RoundRobinLoadBalancer
,如果服务的消费者需要采用随机的负载均衡策略也可以自行定义:
具体操作:
定义随机算法对象,通过@Bean将器加载到Spring容器中
package com.order.config; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.loadbalancer.core.RandomLoadBalancer; import org.springframework.cloud.loadbalancer.core.ReactorLoadBalancer; import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier; import org.springframework.cloud.loadbalancer.support.LoadBalancerClientFactory; import org.springframework.context.annotation.Bean; import org.springframework.core.env.Environment; public class LoadBalancerClient { @Bean ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(Environment environment, LoadBalancerClientFactory loadBalancerClientFactory) { String name = environment.getProperty(LoadBalancerClientFactory.PROPERTY_NAME); return new RandomLoadBalancer(loadBalancerClientFactory .getLazyProvider(name, ServiceInstanceListSupplier.class), name); } }
在
RestTemplate
配置类上方使用@LoadBalancerClient
或者@LoadBalancerClients
注解(根据不同的服务提供方配配置不同的客户端负载均衡算法策略,这里我们使用@LoadBalancerClient
)package com.order.config; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.loadbalancer.annotation.LoadBalancerClient; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @LoadBalancerClient(name = "product-service", configuration = CustomLoadBalancerConfiguration.class) @Configuration public class BeanConfig { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } }
注:
@LoadBalancerClient
注解中的name
表示该负载均衡策略对哪个服务生效(服务提供方),Configuration
表示该负载均衡器使用哪个负载均衡策略。
配置完成后,后续对product-service
服务实例的调用就是随机的了!!