标签:线性 and nlb gap dex 请求 遍历 request 对象
自动化配置
由于 Ribbon 中定义的每一个接口都有多种不同的策略实现,同时这些接口之间又有一定的依赖关系,Spring Cloud Ribbon 中的自动化配置能够很方便的自动化构建接口的具体实现,接口如下:
这些自动化配置内容是在没有引入 Spring Cloud Eureka 等服务治理框架时如此,在同时引入 Eureka 和 Ribbon 依赖时,自动化配置会有一些不同。通过自动化配置的实现,我们可以轻松的实现客户端的负载均衡,同时,针对一些个性化的需求,我们也可以方便的替换上面的这些默认实现,示例代码:
@Configurable
public class RibbonConfiguration {
? ?
????????@Bean
????????public IRule ribbonRule(IClientConfig clientConfig) {
????????????????return new WeightedResponseTimeRule();
????????}
}
可以使用 @RibbonClient 注解来实现更细粒度的客户端配置,创建 ConsumerHelloserviceApplication 主类,使用 @RibbonClient 注解来指定服务使用 WebServiceRibbonConfiguration 配置,代码如下:
@RibbonClient (name = "ORG.DRSOFT.WEBSERVICE.HELLOSERVICE", configuration = RibbonConfiguration.class)
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerHelloserviceApplication {
? ?
????????public static void main(String[] args) {
????????????????SpringApplication.run(ConsumerHelloserviceApplication.class, args);
????????}
? ?
????????@LoadBalanced
????????@Bean
????????public RestTemplate createRestTemplate() {
????????????????return new RestTemplate();
????????}
}
注意:如果需要使服务单独配置,那么配置类不能放在@ComponentScan所扫描的当前包下以及子包下,否则我们自定义的这个配置类就会被所有的Ribbon客户端所共享,@SpringBootApplication 注解中就包含了 @ComponentScan 注解,因此必须使配置类处于不同的包以及子包。
如果需要设置默认配置或者多个@RibbonClient 注解,可以使用 @RibbonClients 注解,其 defaultConfiguration 可以设置默认的自定义配置,配置类不限定所属包,value 可以设置多个 @RibbonClient 注解,示例代码如下:
@RibbonClients (defaultConfiguration = RibbonConfiguration.class)
@EnableDiscoveryClient
@SpringBootApplication
public class ConsumerHelloserviceApplication {
? ?
????????public static void main(String[] args) {
????????????????SpringApplication.run(ConsumerHelloserviceApplication.class, args);
????????}
? ?
????????@Bean
????????@LoadBalanced
????????public RestTemplate restTemplate() {
????????????????return new RestTemplate();
????????}
}
与 Eureka 结合
当在 Spring Cloud 的应用中同时应用 Spring Cloud Ribbon 和 Spring Cloud Eureka 依赖时,会触发 Eureka 中实现的对 Ribbon 的自动化配置,接口实现如下:
负载均衡策略
IRule 接口其Ribbon 实现了非常多的选择策略,下面我们来详细说明一下IRule 接口的定义如下:
public interface IRule{
????????public Server choose(Object key);??
????????public void setLoadBalancer(ILoadBalancer lb);
????????public ILoadBalancer getLoadBalancer();
}
IRule 接口的具体实现:
public Server choose(ILoadBalancer lb, Object key) {
????????????????if (lb == null) {
????????????????????????return null;
????????????????}
????????????????Server server = null;
????????????????while (server == null) {
????????????????????????if (Thread.interrupted()) {
????????????????????????????????return null;
????????????????????????}
????????????????????????List<Server> upList = lb.getReachableServers();
????????????????????????List<Server> allList = lb.getAllServers();
? ?
????????????????????????int serverCount = allList.size();
????????????????????????if (serverCount == 0) {
????????????????????????????????return null;
????????????????????????}
????????????????????????int index = rand.nextInt(serverCount);
????????????????????????server = upList.get(index);
????????????????????????if (server == null) {
????????????????????????????????Thread.yield();
????????????????????????????????continue;
????????????????????????}
????????????????????????if (server.isAlive()) {
????????????????????????????????return (server);
????????????????????????}
????????????????????????server = null;
????????????????????????Thread.yield();
????????????????}
????????????????return server;
????????}
public Server choose(ILoadBalancer lb, Object key) {
????????????????if (lb == null) {
????????????????????????log.warn("no load balancer");
????????????????????????return null;
????????????????}
????????????????Server server = null;
????????????????int count = 0;
????????????????while (server == null && count++ < 10) {
????????????????????????List<Server> reachableServers = lb.getReachableServers();
????????????????????????List<Server> allServers = lb.getAllServers();
????????????????????????int upCount = reachableServers.size();
????????????????????????int serverCount = allServers.size();
????????????????????????if ((upCount == 0) || (serverCount == 0)) {
????????????????????????????????log.warn("No up servers available from load balancer: " + lb);
????????????????????????????????return null;
????????????????????????}
????????????????????????int nextServerIndex = incrementAndGetModulo(serverCount);
????????????????????????server = allServers.get(nextServerIndex);
????????????????????????if (server == null) {
????????????????????????????????/* Transient. */
????????????????????????????????Thread.yield();
????????????????????????????????continue;
????????????????????????}
????????????????????????if (server.isAlive() && (server.isReadyToServe())) {
????????????????????????????????return (server);
????????????????????????}
????????????????????????// Next.
????????????????????????server = null;
????????????????}
????????????????if (count >= 10) {
????????????????????????log.warn("No available alive servers after 10 tries from load balancer: "?+ lb);
????????????????}
????????????????return server;
????????}
public void maintainWeights() {
????????????????????????ILoadBalancer lb = getLoadBalancer();
????????????????????????if (lb == null) {
????????????????????????????????return;
????????????????????????}
????????????????????????if (!serverWeightAssignmentInProgress.compareAndSet(false, true)) {
????????????????????????????????return;
????????????????????????}
????????????????????????try {
????????????????????????????????logger.info("Weight adjusting job started");
????????????????????????????????AbstractLoadBalancer nlb = (AbstractLoadBalancer) lb;
????????????????????????????????LoadBalancerStats stats = nlb.getLoadBalancerStats();
????????????????????????????????if (stats == null) {
????????????????????????????????????????return;
????????????????????????????????}
????????????????????????????????double totalResponseTime = 0;
????????????????????????????????for (Server server : nlb.getAllServers()) {
????????????????????????????????????????ServerStats ss = stats.getSingleServerStat(server);
????????????????????????????????????????totalResponseTime += ss.getResponseTimeAvg();
????????????????????????????????}
????????????????????????????????Double weightSoFar = 0.0;
????????????????????????????????List<Double> finalWeights = new ArrayList<Double>();
????????????????????????????????for (Server server : nlb.getAllServers()) {
????????????????????????????????????????ServerStats ss = stats.getSingleServerStat(server);
????????????????????????????????????????double weight = totalResponseTime - ss.getResponseTimeAvg();
????????????????????????????????????????weightSoFar += weight;
????????????????????????????????????????finalWeights.add(weightSoFar);
????????????????????????????????}
????????????????????????????????setWeights(finalWeights);
????????????????????????} catch (Exception e) {
????????????????????????????????logger.error("Error calculating server weights", e);
????????????????????????} finally {
????????????????????????????????serverWeightAssignmentInProgress.set(false);
????????????????????????}
????????????????}
计算规则为 weightSoFar + totalResponseTime - 实例的平均响应时间,其中 weightSoFar 初始化为零,并且每计算好一个权重值需要累加到 weightSoFar 上供下一次计算使用,假设有4个实例A、B、C、D,他们的平均响应时间为10、40、80、100,所以总响应时间是 230,每个实例的权重为总响应时间与实例自身的平均响应时间的差的累积所得,所以A、B、C、D的权重分别如下所示:
需要注意的是,这里的权重值只表示各实例权重区间的上限,每个实例的权重区间如下:
权重区间的宽度越大,而权重区间的宽度越大,被选中的概率越高
public Server choose(Object key) {
????????????????if (loadBalancerStats == null) {
????????????????????????return super.choose(key);
????????????????}
????????????????List<Server> serverList = getLoadBalancer().getAllServers();
????????????????int minimalConcurrentConnections = Integer.MAX_VALUE;
????????????????long currentTime = System.currentTimeMillis();
????????????????Server chosen = null;
????????????????for (Server server: serverList) {
????????????????????????ServerStats serverStats = loadBalancerStats.getSingleServerStat(server);
????????????????????????if (!serverStats.isCircuitBreakerTripped(currentTime)) {
????????????????????????????????int concurrentConnections = serverStats.getActiveRequestsCount(currentTime);
????????????????????????????????if (concurrentConnections < minimalConcurrentConnections) {
????????????????????????????????????????minimalConcurrentConnections = concurrentConnections;
????????????????????????????????????????chosen = server;
????????????????????????????????}
????????????????????????}
????????????????}
????????????????if (chosen == null) {
????????????????????????return super.choose(key);
????????????????} else {
????????????????????????return chosen;
????????????????}
????????}
? ?
? ?
? ?
笔记:Spring Cloud Ribbon 客户端配置详解
标签:线性 and nlb gap dex 请求 遍历 request 对象
原文地址:http://www.cnblogs.com/li3807/p/7469024.html