/**
* Load balancer that can avoid a zone as a whole when choosing server.
*<p>
* The key metric used to measure the zone condition is Average Active Requests,
which is aggregated per rest client per zone. It is the
total outstanding requests in a zone divided by number of available targeted instances (excluding circuit breaker tripped instances).
This metric is very effective when timeout occurs slowly on a bad zone.
<p>
The LoadBalancer will calculate and examine zone stats of all available zones. If the Average Active Requests for any zone has reached a configured threshold, this zone will be dropped from the active server list. In case more than one zone has reached the threshold, the zone with the most active requests per server will be dropped.
Once the the worst zone is dropped, a zone will be chosen among the rest with the probability proportional to its number of instances.
A server will be returned from the chosen zone with a given Rule (A Rule is a load balancing strategy, for example {@link AvailabilityFilteringRule})
For each request, the steps above will be repeated. That is to say, each zone related load balancing decisions are made at real time with the up-to-date statistics aiding the choice.
*/
publicinterfaceLoadBalancerClientextendsServiceInstanceChooser{//用于执行http负载均衡请求<T> T execute(String serviceId, LoadBalancerRequest<T> request)throws IOException;<T> T execute(String serviceId, ServiceInstance serviceInstance,
LoadBalancerRequest<T> request)throws IOException;//重构URI,替换服务名
URI reconstructURI(ServiceInstance instance, URI original);}
RibbonLoadBalancerClient的execute方法如下
//RibbonLoadBalancerClient#executepublic<T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint)throws IOException {//根据serviceId拿到ILoadBalancer,交由它进行负载均衡
ILoadBalancer loadBalancer =getLoadBalancer(serviceId);//根据loadBalancer拿到真正的服务提供者
Server server =getServer(loadBalancer, hint);if(server == null){thrownewIllegalStateException("No instances available for "+ serviceId);}//包装Server
RibbonServer ribbonServer =newRibbonServer(serviceId, server,isSecure(server, serviceId),serverIntrospector(serviceId).getMetadata(server));//执行请求returnexecute(serviceId, ribbonServer, request);}//RibbonLoadBalancerClient#getLoadBalancerprotected ILoadBalancer getLoadBalancer(String serviceId){//从clientFactory中获得该服务对应的ILoadBalancer returnthis.clientFactory.getLoadBalancer(serviceId);}
//DiscoveryEnabledNIWSServerList#obtainServersViaDiscoveryprivate List<DiscoveryEnabledServer>obtainServersViaDiscovery(){
List<DiscoveryEnabledServer> serverList =newArrayList<DiscoveryEnabledServer>();//...//拿到Eureka客户端,它可以进行服务拉取,注册等
EurekaClient eurekaClient = eurekaClientProvider.get();if(vipAddresses!=null){for(String vipAddress : vipAddresses.split(",")){// if targetRegion is null, it will be interpreted as the same region of client
List<InstanceInfo> listOfInstanceInfo = eurekaClient.getInstancesByVipAddress(vipAddress, isSecure, targetRegion);for(InstanceInfo ii : listOfInstanceInfo){if(ii.getStatus().equals(InstanceStatus.UP)){//... 封装服务并保存
DiscoveryEnabledServer des =createServer(ii, isSecure, shouldUseIpAddr);
serverList.add(des);}}if(serverList.size()>0&& prioritizeVipAddressBasedServers){break;// if the current vipAddress has servers, we dont use subsequent vipAddress based servers}}}return serverList;}
Ribbon原理解析1.引言什么是RibbonRibbon是Netflix公司的一个负载均衡项目,可以在进行服务调用时做负载均衡;2.Ribbon基本使用Ribbon结合HttpRibbon通常和Http请求结合,对Http请求进行负载均衡;最简单的使用如下,通过注入RestTemplate,并且打上@LoadBlanced注解,即可得到一个带有负载均衡效果的RestTemplate@Configurationpublic class HttpConfiguration {