在Spring cloud有两种服务调用方式,一种是ribbon+restTemplate,另一种是feign,feign注解化更方便使用。 ribbon是一个负载均衡客户端,可以很好的控制http和tcp的一些行为。Feign默认集成了ribbon。RestTemplate中 @LoadBalanced表明这个restRemplate开启负载均衡的功能。
Feign
1,添加依赖
org.springframework.cloud
spring-cloud-starter-openfeign
2,在启动类上添加注解
@EnableFeignClients
3,写一个接口,用来声明调用哪个方法
/**
* @FeignClient(name = "product")是访问的服务的名称
* @GetMapping("/msg")这是调用服务的接口
*/
@FeignClient(name = "product")
public interface ProductClient {
@GetMapping("/msg")
String productMsg();
}
4,在controller中调用接口
@Autowired
private ProductClient productClient;
@GetMapping("/getMsg")
public String getMsg(){
String result = productClient.productMsg();
log.info("result={}",result);
return result;
}
这个Feign中用了ribbon负载均衡的组件,所以默认情况下使用轮询的算法,当然还有这么多可选择的算法。
Rest Template
Rest Template的实现方式有三种。
1,直接写路径的方式,有多个的话就用,分割,url写死
RestTemplate restTemplate = new RestTemplate();
String response = restTemplate.getForObject("http://localhost:8080/msg",String.class);
2,填写这个服务的名称,然后进行调用。
使用loadBalancerClient获取url,然后进行调用
RestTemplate restTemplate = new RestTemplate();
ServiceInstance serviceInstance = loadBalancerClient.choose("PRODUCT");
String url = String.format("http://%s:%s",serviceInstance.getHost(),serviceInstance.getPort()+"/msg");
String response = restTemplate.getForObject(url,String.class);
3,直接找到接口方法来调用
@Autowired
private RestTemplateConfig config;
String response = config.getForObject("http://PRODUCT/msg",String.class);
return response;
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
追踪源码
点击choose方法
我们可以看到这儿有一个获取serviceId的方法
public ServiceInstance choose(String serviceId) {
Server server = this.getServer(serviceId);
return server == null ? null : new RibbonLoadBalancerClient.RibbonServer(serviceId, server, this.isSecure(server, serviceId), this.serverIntrospector(serviceId).getMetadata(server));
}
用这个ILoadBalancer 来找serviceId,这个就是ribbon内置的组件
protected Server getServer(ILoadBalancer loadBalancer) {
return loadBalancer == null ? null : loadBalancer.chooseServer("default");
}
我们来看一下这个ILoadBalancer的接口
public interface ILoadBalancer {
void addServers(List var1);
Server chooseServer(Object var1);
void markServerDown(Server var1);
/** @deprecated */
@Deprecated
List getServerList(boolean var1);
List getReachableServers();
List getAllServers();
}
这种底层的负载均衡地基本上全都是用的ribbon的组件,ribbon就是处理负载均衡的。