【Spring-Cloud】核心源码分析 高级篇

好几年没有更新博客了,满屋子都是灰尘

1. Ribbon源码之负载均衡

1.1 分析入口 @LoadBalanced

只提出最重要的代码 代码里 “// 重点” 的地方

public class RibbonLoadBalancerClient implements LoadBalancerClient {
	public <T> T execute(String serviceId, LoadBalancerRequest<T> request, Object hint) throws IOException {
		ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
		Server server = getServer(loadBalancer, hint); // 重点
		if (server == null) {
			throw new IllegalStateException("No instances available for " + serviceId);
		}
		RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server,
				serviceId), serverIntrospector(serviceId).getMetadata(server));

		return execute(serviceId, ribbonServer, request);
	}
    
	protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
    	if (loadBalancer == null) {
    		return null;
    	}
    	// Use 'default' on a null hint, or just pass it on?
    	return loadBalancer.chooseServer(hint != null ? hint : "default"); // 重点
    }
}

public class BaseLoadBalancer {
    // 轮询负载均衡策略
    private final static IRule DEFAULT_RULE = new RoundRobinRule(); // 重点
    
    protected IRule rule = DEFAULT_RULE; // 重点
    
    public Server chooseServer(Object key) {
        if (counter == null) {
            counter = createCounter();
        }
        counter.increment();
        if (rule == null) {
            return null;
        } else {
            try {
                return rule.choose(key); // 重点
            } catch (Exception e) {
                logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", name, key, e);
                return null;
            }
        }
    }
}

// Server 元数据
public class Server {
    public static final String UNKNOWN_ZONE = "UNKNOWN";
    private String host;
    private int port = 80;
    private String scheme;
    private volatile String id;
    private volatile boolean isAliveFlag;
    private String zone = UNKNOWN_ZONE;
    private volatile boolean readyToServe = true;
}

1.2 解释

1. 首先从注册中心获取provider的列表
2. 通过一定的策略选择其中一个节点
3. 再返回给restTemplate调用

2. Feign

2.1 分析入口

public class LoadBalancerFeignClient implements Client {
	@Override
	public Response execute(Request request, Request.Options options) throws IOException {
		try {
			URI asUri = URI.create(request.url());
			String clientName = asUri.getHost();
			URI uriWithoutHost = cleanUrl(request.url(), clientName);
			FeignLoadBalancer.RibbonRequest ribbonRequest = new FeignLoadBalancer.RibbonRequest(
					this.delegate, request, uriWithoutHost);

			IClientConfig requestConfig = getClientConfig(options, clientName);
			return lbClient(clientName).executeWithLoadBalancer(ribbonRequest,
					requestConfig).toResponse();
		}
		catch (ClientException e) {
			IOException io = findIOException(e);
			if (io != null) {
				throw io;
			}
			throw new RuntimeException(e);
		}
	}
}

public static class Options {
    private final int connectTimeoutMillis;
    private final int readTimeoutMillis;
    private final boolean followRedirects;
    public Options() {
      this(10 * 1000, 60 * 1000);
    }
}

eign:
  client:
    config:
      default:
        connectTimeout: 2000
        readTimeout: 2000

3. Hystrix源码之降级策略

3.1 隔离策略

execution.isolation.strategy
THREAD 线程池(默认)
SEMAPHORE 信号量(信号量适用于接口并发量高的情况,如每秒数千次调用的情况,导致的线程开销过高,通常只适用于非网络调用,执行速度快)

3.2 超时时间

execution.isolation.thread.timeoutInMilliseconds
如果使用Hystrix,要设置该时间,该时间要比Ribbon和Feign的优先级高

3.3 是否开启超时

execution.timeout.enabled

3.4 最大并发数

execution.isolation.semaphore.maxConcurrentRequests(隔离策略为 信号量的时候,如果达到最大并发数时,后续请求会被拒绝,默认是10)

你可能感兴趣的:(【Spring-Cloud】核心源码分析 高级篇)