core:Java功能增強 —— 攔截器
通過@LoadBalanced修飾就可以為應(yīng)用引入Ribbon框架來實現(xiàn)負(fù)載均衡。
@Configuration
public class ConfigBean {
/**
* 使用@LoadBalanced開啟負(fù)載均衡
* RestTemplate 通過它來訪問服務(wù)
* */
@LoadBalanced
@Bean
RestTemplate restTemplate() {
return new RestTemplate();
}
}
使用時這樣(jServer1就是注冊在eureka的服務(wù)名):
@RestController
@RequestMapping("/")
public class HelloController {
@Autowired
RestTemplate restTemplate;
@RequestMapping("/hello")
public String hello() {
String result = restTemplate.getForEntity("http://jServer1/hello",String.class).getBody();
System.out.println(result);
return result;
}
}
所以Ribbon的核心在于@LoadBalanced,那它引入了哪些東西呢?進(jìn)入看一下:

image.png
立刻明白了什么,是老朋友攔截器啊,所以是攔截了請求,然后根據(jù)負(fù)載均衡策略找到合適的服務(wù)實例,再發(fā)請求出去么。
intercept方法如下:
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
URI originalUri = request.getURI();
String serviceName = originalUri.getHost();
return (ClientHttpResponse)this.loadBalancer.execute(serviceName, new LoadBalancerRequest<ClientHttpResponse>() {
public ClientHttpResponse apply(ServiceInstance instance) throws Exception {
HttpRequest serviceRequest = LoadBalancerInterceptor.this.new ServiceRequestWrapper(request, instance);
return execution.execute(serviceRequest, body);
}
});
}
進(jìn)到execute方法:
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
ILoadBalancer loadBalancer = this.getLoadBalancer(serviceId);
//就是這里了?。? Server server = this.getServer(loadBalancer);
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));
RibbonLoadBalancerContext context = this.clientFactory.getLoadBalancerContext(serviceId);
RibbonStatsRecorder statsRecorder = new RibbonStatsRecorder(context, server);
try {
T returnVal = request.apply(ribbonServer);
statsRecorder.recordStats(returnVal);
return returnVal;
} catch (IOException var9) {
statsRecorder.recordStats(var9);
throw var9;
} catch (Exception var10) {
statsRecorder.recordStats(var10);
ReflectionUtils.rethrowRuntimeException(var10);
return null;
}
}
}
protected Server getServer(ILoadBalancer loadBalancer) {
return loadBalancer == null ? null : loadBalancer.chooseServer("default");
}
以最基本的BaseLoadBalancer為例(還有其他Balancer實現(xiàn)):
public Server chooseServer(Object key) {
if (this.counter == null) {
this.counter = this.createCounter();
}
this.counter.increment();
if (this.rule == null) {
return null;
} else {
try {
//這里的rule = DEFAULT_RULE = new RoundRobinRule();
return this.rule.choose(key);
} catch (Throwable var3) {
return null;
}
}
}
可以發(fā)現(xiàn)是根據(jù)IRule.choose(key)來選擇服務(wù)器實例的,而IRule就是負(fù)載均衡策略接口,可以看出已經(jīng)默認(rèn)實現(xiàn)了很多種策略:

image.png