服务调用
四.Ribbon
1.Ribbon知识点
Ribbon是用于负载均衡的客户端工具,很遗憾目前官网宣布rRbbon已进入维护状态
一句话总结:Ribbon = 负载均衡 + RestTemplate调用
2.getForObject和getForEntity
getForObject
返回对象为响应体中数据转化成的对象,基本上可以理解为Json
getForEntity
返回对象为ResponseEntity对象,包括了响应中的一些重要信息,比如响应头、响应状态码、响应体等
①修改老order80的controller代码
添加如下代码
@GetMapping(value = "/consumer/payment/getForEntity/{id}")
public CommonResult<Payment> getPayment1(@PathVariable("id") Long id){
ResponseEntity<CommonResult> entity = restTemplate.getForEntity(PAYMENT_URL + "/payment/get/" + id, CommonResult.class);
if (entity.getStatusCode().is2xxSuccessful()){
//返回请求体
return entity.getBody();
}else{
return new CommonResult<>(444,"操作失败");
}
}
启动老Order80,先启动7001,再启动8001和80
访问
3.postForObject和postForEntity
写法都差不多,可也参考之前的代码写postForEntity自行测试。
4.Ribbon核心组件IRule
①IRule:根据特定算法从服务列表中选取一个要访问的服务
如何替换
注意
所以不能在之前的包结构下写Ribbon的替换规则,我们新建一个不同于springcloud的包myrule,二者为同级
②创建MyRule配置类
在myrule包新建类
package com.hry.myrule;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyRule {
@Bean
public IRule myIRule(){
//规则定义为随机
return new RandomRule();
}
}
③修改80主启动类
新增注解
name是支付微服务的应用名称,第二个是配置类。
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MyRule.class)
④测试
将8001配置改为集群版(8002之前是集群版没修改为单机版,因此不用修改为集群版)
依次启动7001,8001,8002,80,之前轮询时是8001,8002交替的
现在从轮询变为随机
5.Ribbon默认负载——轮询算法
①原理(取余)
②手写算法
了解JUC(CAS+自旋锁)
(1)修改8001和8002的controller,添加如下代码
@GetMapping(value = "/payment/lb")
public String getPaymentLB(){
return serverPort;
}
(2)将80配置类中的@LoadBalance注解注释掉
(3)在80编写自己的算法接口和实现类
package com.hry.springcloud.lb;
import org.springframework.cloud.client.ServiceInstance;
import java.util.List;
public interface LoadBalance {
ServiceInstance instances(List<ServiceInstance> serviceInstances);
}
package com.hry.springcloud.lb.impl;
import com.hry.springcloud.lb.LoadBalance;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@Component
public class LoadBalanceImpl implements LoadBalance {
private AtomicInteger atomicInteger = new AtomicInteger(0);
public final int getAndIncrement(){
int current;
int next;
do{
current = this.atomicInteger.get();
//Integer.MAX_VALUE = 2147483647 = 7fff ffff
next = (current >= 2147483647) ? 0 : current + 1;
}while (!this.atomicInteger.compareAndSet(current,next));
return next;
}
@Override
public ServiceInstance instances(List<ServiceInstance> serviceInstances) {
int index = getAndIncrement() % serviceInstances.size();
return serviceInstances.get(index);
}
}
(4)修改80的controller
@Resource
private DiscoveryClient discoveryClient;
/**
* 自己的轮询算法
*/
@Resource
private LoadBalance loadBalance;
@GetMapping(value = "/consumer/payment/lb")
public String getPaymentLB(){
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
if (instances == null || instances.size() <= 0){
return null;
}
ServiceInstance serviceInstance = loadBalance.instances(instances);
return restTemplate.getForObject(serviceInstance.getUri() + "/payment/lb",String.class);
}
⑤修改80的主启动类
把RibbonClient注解注释掉
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MyRule.class)
⑥测试
重启8001,8002,80