カスタム負荷等化ポーリングアルゴリズム-Ribbonベースのポーリングアルゴリズム
一:LoadBalanceインタフェースのカスタマイズ
具体的なコードは以下の通りです.
このインタフェースには、次の2つの機能があります.
二:負荷均衡ポーリングアルゴリズムを採用してこのインタフェースを実現する
1.上のLoadBalanceインタフェースを実現する
注意:
2.CAS+スピンロック方式でポーリングアルゴリズムを実現
CAS+スピンロックを採用する理由:負荷等化で使用するシーンは高同時性であるため、ポーリングアルゴリズムの核心は1つの整数型の下付き文字を得ることであり、高同時性のシーンの下で、この下付き文字のデータの一致性を保証する必要があり、CASはこの下付き文字のデータの一致性を保証することができ、スピンロックはこの要求の絶え間ないアクセスを成功するまで再試行することができる.CAS+スピンロックは、高効率かつ安全性の下でマイクロサービスの高可用性を保証できるためである.
——————————————————————————————————————
AtomicIntegerを採用した理由:
——————————————————————————————————————
CAS操作
——————————————————————————————————————
スピンロック:
Currentは、現在の下付き文字を取得し、CASの比較に使用します.
nextの付与には3つの演算子が使用され、サービス呼び出しの回数が整数の最大値を超えると0にリセットされます.そうしないと、現在の下付き文字の値を変更するために1つ追加されます.
2.このポーリングアルゴリズムによって生成された値を取得し、パラメータマイクロサービスインスタンスListの下付き
呼び出しが必要なマイクロサービスインスタンスの下のラベルを取得するには、余剰取得法を使用します.
最後に、この下付き文字で取得したインスタンスを返します.
三:この負荷等化ポーリング方法を呼び出して負荷等化を実現する
具体的な手順:
注意:1.discoveryClientというオブジェクトを取得するには、アプリケーション起動クラスに@EnableDiscoveryClient注記を追加する必要があります2.restTemplateというオブジェクトを取得するには、まずrestTemplateというオブジェクトを注入する必要があります
具体的なコードは以下の通りです.
package com.springcloudtest.order.config;
import org.springframework.cloud.client.ServiceInstance;
import java.util.List;
public interface LoadBalance {
ServiceInstance instances(List<ServiceInstance> serviceInstanceList);
}
このインタフェースには、次の2つの機能があります.
1. , , instances , List,
2. , , ,
二:負荷均衡ポーリングアルゴリズムを採用してこのインタフェースを実現する
1.上のLoadBalanceインタフェースを実現する
package com.springcloudtest.order.config;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@Component
public class MyLoadBalance implements LoadBalance {
public ServiceInstance instances(List<ServiceInstance> serviceInstanceList) {
return null;
}
}
注意:
@Component, IOC , @Resource
2.CAS+スピンロック方式でポーリングアルゴリズムを実現
package com.springcloudtest.order.config;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
@Component
public class MyLoadBalance implements LoadBalance {
// Integer,
private AtomicInteger atomicInteger = new AtomicInteger(0);
/**
* CAS +
* @return
*/
public final int getServiceCallSubscript(){
//
int current;
//
int next;
//
do{
//
current = this.atomicInteger.get();
next = current >=Integer.MAX_VALUE ? 0 :current+1;
//CAS , ,
}while (!this.atomicInteger.compareAndSet(current,next));
System.out.println("next:--------"+next);
return next;
}
public ServiceInstance instances(List<ServiceInstance> serviceInstanceList) {
return null;
}
}
CAS+スピンロックを採用する理由:負荷等化で使用するシーンは高同時性であるため、ポーリングアルゴリズムの核心は1つの整数型の下付き文字を得ることであり、高同時性のシーンの下で、この下付き文字のデータの一致性を保証する必要があり、CASはこの下付き文字のデータの一致性を保証することができ、スピンロックはこの要求の絶え間ないアクセスを成功するまで再試行することができる.CAS+スピンロックは、高効率かつ安全性の下でマイクロサービスの高可用性を保証できるためである.
——————————————————————————————————————
// Integer,
private AtomicInteger atomicInteger = new AtomicInteger(0);
AtomicIntegerを採用した理由:
, ,
, CAS
——————————————————————————————————————
this.atomicInteger.compareAndSet(current,next)
CAS操作
comapreAndSet comapreAndSwap, ,
( ), ,
,
——————————————————————————————————————
do{
//
current = this.atomicInteger.get();
next = current >=Integer.MAX_VALUE ? 0 :current+1;
//CAS , ,
}while (!this.atomicInteger.compareAndSet(current,next));
System.out.println("next:--------"+next);
return next;
}
スピンロック:
, do....while , , CAS
, , ,
current = this.atomicInteger.get();
Currentは、現在の下付き文字を取得し、CASの比較に使用します.
next = current >=Integer.MAX_VALUE ? 0 :current+1;
nextの付与には3つの演算子が使用され、サービス呼び出しの回数が整数の最大値を超えると0にリセットされます.そうしないと、現在の下付き文字の値を変更するために1つ追加されます.
2.このポーリングアルゴリズムによって生成された値を取得し、パラメータマイクロサービスインスタンスListの下付き
public ServiceInstance instances(List<ServiceInstance> serviceInstanceList) {
//
int index = getServiceCallSubscript()%serviceInstanceList.size();
// serviceInstanceList ServiceInstance
return serviceInstanceList.get(index);
}
呼び出しが必要なマイクロサービスインスタンスの下のラベルを取得するには、余剰取得法を使用します.
: index = current %
index List
current
List
最後に、この下付き文字で取得したインスタンスを返します.
三:この負荷等化ポーリング方法を呼び出して負荷等化を実現する
package com.springcloudtest.order.controller;
import com.springcloudtest.order.config.LoadBalance;
import com.springcloudtest.order.config.MyLoadBalance;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.net.URI;
import java.util.List;
@Controller
public class TestController {
@Value("${server.port}")
private String serverPort;
@Resource
private LoadBalance myLoadBalance;
@Resource
private DiscoveryClient discoveryClient;
@Resource
private RestTemplate restTemplate;
@RequestMapping("/order/myLoadBalance")
@ResponseBody
public String myLoadBalance(){
// payment-springcloud List
List<ServiceInstance> serviceInstanceList = discoveryClient.getInstances("payment-springcloud");
// List , , null
if(CollectionUtils.isEmpty(serviceInstanceList)){
return null;
}
// List ,
ServiceInstance serviceInstance = myLoadBalance.instances(serviceInstanceList);
//
URI uri = serviceInstance.getUri();
return restTemplate.postForObject(uri+"/payment/consul",null,String.class);
}
}
具体的な手順:
1. payment-springcloud List
2. instances ,
3. URI , restTemplate ,
注意:1.discoveryClientというオブジェクトを取得するには、アプリケーション起動クラスに@EnableDiscoveryClient注記を追加する必要があります2.restTemplateというオブジェクトを取得するには、まずrestTemplateというオブジェクトを注入する必要があります