赞
踩
利用 springcloud提供的 DiscoveryClient 服务发现功能,获取注册在注册中心的服务列表,然后根据一定算法从该列表中选择一个作为本次调用服务的服务提供者。
微服务项目,需要有注册中心,有服务提供者和服务消费者
本例使用 eureka 作为注册中心,两个提供者,一个消费者
使用 RestTemplate 作为远程调用的client
注意不要使用 @LoadBalanced 这个负载均衡的注解
package com.li.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; /** * @author liql * @date 2021/8/7 */ @Configuration public class RestTemplateConfig { @Bean // @LoadBalanced //开启负载均衡, public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
public interface MyLoadBalance {
ServiceInstance getIntacnce(List<ServiceInstance> serviceInstances);
}
package com.li.config; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.client.ServiceInstance; import org.springframework.stereotype.Component; import java.util.List; import java.util.Random; /** * @author liql * @date 2021/8/11 */ @Component @Slf4j public class MyLoadBalanceImpl implements MyLoadBalance { /** * * @param serviceInstances 某个服务的服务实例列表 本次的为 PROVIDER-SERVICE 服务实例列表 * @return */ //自定义随机策略 @Override public ServiceInstance getIntacnce(List<ServiceInstance> serviceInstances) { Random random = new Random(); //生成随机的 服务实例下标 int index = random.nextInt(serviceInstances.size()); log.info("获得的微服务的对应下标为:{}",index); //返回服务实例给调用者 return serviceInstances.get(index); } }
package com.li.controller; import com.li.config.MyLoadBalance; import com.li.entities.Provider; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.net.URI; /** * @author liql * @date 2021/8/11 */ @Slf4j @RestController public class MyLoadBalanceController { @Autowired private MyLoadBalance myLoadBalance; @Autowired private DiscoveryClient discoveryClient; @Autowired private RestTemplate restTemplate; @PostMapping("/myloadbalance") public String test(@RequestBody Provider provider){ //获取特定服务的服务实例列表 List<ServiceInstance> instances = discoveryClient.getInstances("PROVIDER-SERVICE"); if (instances==null||instances.size()==0) return "无可用服务"; //获取自定义策略的服务实例 ServiceInstance intacnce = myLoadBalance.getIntacnce(instances); //获取实例的url URI uri = intacnce.getUri(); log.info("获得的url:{}",uri); return restTemplate.postForObject(uri+"/provider", provider, String.class); } }
每次调用都重新获取服务列表实例,是为了防止 有的实例出现故障后,还存在列表中。
被调用的实例下标为 0 和1,且是不规则出现的,说明 随机策略实现成功。
如果要写其他策略,原理都大同小异。
package com.li.config; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.client.ServiceInstance; import org.springframework.stereotype.Component; import java.util.List; import java.util.Random; import java.util.concurrent.atomic.AtomicInteger; /** * @author liql * @date 2021/8/11 */ @Component @Slf4j public class MyLoadBalanceImpl implements MyLoadBalance { //用来记录访问次数,每访问一次,就加 1 private final AtomicInteger atomicInteger= new AtomicInteger(0); @Override public ServiceInstance getRobin(List<ServiceInstance> serviceInstances){ int last; int current; do { last=atomicInteger.get(); //三元运算 解决访问次数超过 int类型最大值问题 current=last>Integer.MAX_VALUE ? 0 : last+1; }while (!this.atomicInteger.compareAndSet(last, current)); log.info("已经调用了{} 次, 本次调用的下标为 {}",last,current% serviceInstances.size()); //返回调用的实例 注意取余 return serviceInstances.get(current % serviceInstances.size()); } }
@PostMapping("/myloadbalance2")
public String testRobin(@RequestBody Provider provider){
//获取特定服务的服务实例列表
List<ServiceInstance> instances = discoveryClient.getInstances("PROVIDER-SERVICE");
if (instances==null||instances.size()==0)
return "无可用服务";
//获取自定义策略的服务实例
ServiceInstance intacnce = myLoadBalance.getRobin(instances);
//获取实例的url
URI uri = intacnce.getUri();
log.info("获得的url:{}",uri);
return restTemplate.postForObject(uri+"/provider", provider, String.class);
}
测试
轮询策略完成
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。