目录
- 前言
- SpringCloud Ribbon 负载均衡
- 一需求
- 二.RestTemplate远程调用配置负载均衡(order服务内修改)
- 三.Ribbon实现负载均衡的原理
- 四.Ribbon负载均衡策略
- 1.负载均衡种类
- 2.配置负载均衡(order服务中配置)
- 五.Ribbon的饥饿加载配置(在order服务配置)
前言
微服务中比如用户服务部署多台服务器,怎么调用其中某一服务呢?
这里有组件的讲解 → SpringCloud组件原理和面试题
SpringCloud Ribbon 负载均衡
SpringCloud Feign 远程调用实战
一需求
假设现在用户服务部署在两台或者多台服务器上,订单用户怎么去访问某一个?
二.RestTemplate远程调用配置负载均衡(order服务内修改)
1.修改远程调用用户的代码
@Autowired
private RestTemplate restTemplate;
public Order queryOrderById(Long orderId) {
// 根据订单id查询订单
Order order = orderMapper.findById(orderId);
// 利用RestTemplate发起http请求,根据用户id查询用户
// 把localhost改为服务名称
这里这里 String url = "http://userservice/user/" + order.getUserId();
//String url = "http://localhost:8081/user/" + order.getUserId();
// 发送http请求,实现远程调用,现在是get请求类型
User user = restTemplate.getForObject(url, User.class);
// 封装user到Order
order.setUser(user);
// 返回值
return order;
}
注意: Feign集成了Ribbon,不用去特别配置负载均衡。
2.RestTemplate配置类加上注解
/**
* 创建RestTemplate并注入Spring容器
*/
@Bean
@LoadBalanced //负载均衡注解
public RestTemplate restTemplate() {
return new RestTemplate();
}
三.Ribbon实现负载均衡的原理
Ctrl + N 快速查找类:原理是 LoadBalancerInterceptor 实现了 ClientHttpRequestInterceptor 接口。
客户端http请求拦截器
@FunctionalInterface
public interface ClientHttpRequestInterceptor {
ClientHttpResponse intercept(HttpRequest var1, byte[] var2, ClientHttpRequestExecution var3) throws IOException;
}
public class LoadBalancerInterceptor implements ClientHttpRequestInterceptor {
重写ClientHttpRequestInterceptor接口的方法
@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,final ClientHttpRequestExecution execution) throws IOException {
// 1.获取http的请求地址
final URI originalUri = request.getURI();
// 2.获取服务的名称
String serviceName = originalUri.getHost();
Assert.state(serviceName != null,"Request URI does not contain a valid hostname: " + originalUri);
//3.我们进去execute方法:就是为了从Eureka-Server拉取信息
return this.loadBalancer.execute(serviceName,this.requestFactory.createRequest(request, body, execution));
}
}
public class RibbonLoadBalancerClient implements LoadBalancerClient {
//4.进入此方法
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
//调用下面的execute方法
return this.execute(serviceId, (LoadBalancerRequest)request, (Object)null);
}
public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {
//5.根据服务名称获取对应的服务列表,loadBalancer里面有List存有服务的地址
ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
//6.根据算法选择要使用的服务,会进入IRule接口里面,默认是轮询算法
Server server = this.getServer(loadBalancer, hint);
if (server == null) {
throw new IllegalStateException("No instances available for " + serviceId);
} else {
RibbonLoadBalancerClient.RibbonServer ribbonServer = new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
return this.execute(serviceId, (ServiceInstance)ribbonServer, (LoadBalancerRequest)request);
}
}
}
四.Ribbon负载均衡策略
Ribbon负载均衡策略是 IRule接口定义的,每一个子接口都是一种策略。下面是常见负载均衡算法
1.负载均衡种类
负载均衡类 | 规则 |
---|---|
RoundRobinRule | 轮询选择服务器。Ribbon默认负载均衡算法。 |
AvailabilitvFilteringRule | (1) 默认情况,服务器连接3次失败,服务器设置为短路状态。短路状态持续30秒,如果再连接失败,短路状态持续时间就会几何级增长。 (2)并发数高的服务器。可配置该规则会忽略并发数高的服务器。并发数上限可以配置。 |
WeightedResponseTimeRule | 给服务器赋予权重。响应时间越长,权重越小。权重影响服务器的选择。 |
ZoneAvoidanceRule | 使用Zone对服务器进行分类。Zone可以是一个机房、一个机架等。然后对Zone内的服务进行轮询。例如:配置Zone是曹县机房,然后服务提供者会优先选择曹县机房的服务器。 |
BestAvailableRule | 忽略短路的服务器并选择并发数低的服务器。 |
RandomRule | 随机选择一个可用服务器。 |
RetryRule | 重试机制的选择逻辑。 |
2.配置负载均衡(order服务中配置)
(1) 代码类型
注意:这种配置是全局的,订单服务不光调用用户服务是随机的,调用其他的服务也是随机的
//注入新的负载均衡算法 在启动类内注入也可以自定义配置类
@Bean
public IRule randomRule() {
//随机选取一个可用服务器
return new RandomRule();
}
(2) yml中配置
注意:这种局部配置,只针对用户服务去选择负载均衡的算法
userservice: # 服务名称
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.RandomRule # 负载均衡规则
五.Ribbon的饥饿加载配置(在order服务配置)
Ribbon默认是懒加载: 第一次加载才会创建 LoadBalancerClient ,请求时间会很长。
饥饿加载: 在项目启动时创建,降低第一次访问的耗时。
(1) 单个服务配置饥饿加载(在yml文件配置)
ribbon:
eager-load:
enabled: true # 开启饥饿加载
clients: userservice # 指定饥饿加载的服务名称
(1) 多个服务配置饥饿加载(在yml文件配置)
ribbon:
eager-load:
enabled: true # 开启饥饿加载
clients: # 指定饥饿加载的服务名称
- userservice # 用户服务
- cangkuservice # 仓库服务
- zhifuservice # 支付服务