1.センチネルとは
SentinelはAliのオープンソースプロジェクトであり、フロー制御、回路ブレーカーの劣化、システム負荷保護などの複数の側面を提供して、サービス間の安定性を確保します。
公式ウェブサイト:https://github.com/alibaba/Sentinel/wiki
Sentinelの主な機能:
SentinelとHystrixの違い
SentinelとHystrixの違いについては、https://yq.aliyun.com/articles/633786/を参照してください。
一般に:
Hystrixで一般的に使用されるスレッドプールの分離により、スレッドのアップとダウンの切り替えのオーバーヘッドが比較的大きくなります。Hystrixで使用されるセマフォの分離は、特定のリソースへの同時呼び出しの数を制御します。効果は良好ですが、遅い呼び出しではできません。自動的にダウングレードされます。Sentinelは同時スレッドの数を使用します。フロー制御は信号分離の機能を提供します。
さらに、Sentinelは、さまざまなインジケーターのフロー制御とヒューズを実行できる、より多くのヒューズ劣化寸法をサポートし、より強力なリアルタイムの監視および制御パネルを提供します。
次に、コード例
公式ウェブサイトで提供されているクイックスタートデモに従って、Sentinelを使用して現在の制限とダウングレードを実現する方法を見てみましょう。
この記事のコードを参照してください:githubコード
注意:
- JDK> = 1.7;
- Sentinelのバージョンは1.7.0です。
Sentineljarパッケージを紹介します。
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.7.0</version>
</dependency>
1.電流制限
電流制限の使用と導入については、Sentinel FlowControlを参照してください。
フロー制御(フロー制御)の原則は、アプリケーショントラフィックのQPSまたは同時スレッド数やその他のインジケーターを監視することです。指定されたしきい値に達すると、フローが制御され、システムが瞬間的なトラフィックのピークに圧倒されるのを防ぎます。高いアプリケーションの可用性を確保します。
以下に簡単な例を書いて、Sentinelを使用して電流制限を実現する方法を確認してください。
最初に、後続のインターフェイスの電流制限の例のために、単純な順序クエリインターフェイスを記述します。
@Component
public class OrderQueryService {
public String queryOrderInfo(String orderId) {
System.out.println("获取订单信息:" + orderId);
return "return OrderInfo :" + orderId;
}
}
@Controller
@RequestMapping("order")
public class OrderController {
@Autowired
private OrderQueryService orderQueryService;
@RequestMapping("/getOrder")
@ResponseBody
public String queryOrder1(@RequestParam("orderId") String orderId) {
return orderQueryService.queryOrderInfo(orderId);
}
}
通常の状況では、OrderControllerで注文クエリインターフェイスを呼び出すと、注文情報が返されます。インターフェイスからアクセスされるQPSを2未満に制御するにはどうすればよいですか。Sentienl電流制限は、次の実装方法を提供します。
Sentienlの使用方法。
まず、現在を制限するインターフェイス、制限されるQPSの量、制限する発信者アプリなど、現在の制限ルールを定義する必要があります。
public void initFlowQpsRule() {
List<FlowRule> rules = new ArrayList<FlowRule>();
FlowRule rule1 = new FlowRule();
rule1.setResource(KEY);
// QPS控制在2以内
rule1.setCount(2);
// QPS限流
rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);
rule1.setLimitApp("default");
rules.add(rule1);
FlowRuleManager.loadRules(rules);
}
電流制限を実装する方法はたくさんありますが、この記事では2つの一般的な方法のみをリストしています。
(1)現在の制限の実装方法1:例外をスローしてリソースを定義する
このメソッドはコードに非常に煩わしいため、コードはインターフェイスが呼び出されるtry-catch
スタイルAPIを介してパッケージ化する必要があります。
/**
* 限流实现方式一: 抛出异常的方式定义资源
*
* @param orderId
* @return
*/
@RequestMapping("/getOrder1")
@ResponseBody
public String queryOrder2(@RequestParam("orderId") String orderId) {
Entry entry = null;
// 资源名
String resourceName = KEY;
try {
// entry可以理解成入口登记
entry = SphU.entry(resourceName);
// 被保护的逻辑, 这里为订单查询接口
return orderQueryService.queryOrderInfo(orderId);
} catch (BlockException blockException) {
// 接口被限流的时候, 会进入到这里
log.warn("---getOrder1接口被限流了---, exception: ", blockException);
return "接口限流, 返回空";
} finally {
// SphU.entry(xxx) 需要与 entry.exit() 成对出现,否则会导致调用链记录异常
if (entry != null) {
entry.exit();
}
}
}
テスト、QPS> 2の場合、インターフェイスは次を返します。
ログ出力の表示:
ここで、Sentinelのデフォルトのログ出力ファイルの場所は次のとおりであることに注意してください。/{userhome}/logs/csp/
インターフェイスがスロットリングしているときに、Sentinelが出力するログを見てみましょう。
ログの形式は次のとおりです。タイムスタンプ| 2番目に発生した最初のリソース|リソース名、傍受の理由、インターフェイス呼び出しのソース、|傍受されたリソースの呼び出し元、傍受された数
ログの説明については、Sentienlログを参照してください。
(2)電流制限実現方法2:注釈法はリソースを定義します
上記のtry-catch
スタイルAPIは現在の制限を実現できますが、コードに煩わしすぎるため、アノテーションを使用してこれを実現することをお勧めします。以下に記載されていない場合は、注釈を使用してデフォルトで実装されます。
アノテーションの使用については、Sentinelアノテーションの使用を参照してください。
まず、アノテーションをサポートするjarパッケージを導入する必要があります。
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>${sentinel.version}</version>
</dependency>
センチネルアスペクト構成:
@Configuration
public class SentinelAspectConfiguration {
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
}
インターフェイスOrderQueryServiceで、アノテーションを使用して、注文クエリインターフェイスの現在の制限を実装します。
/**
* 订单查询接口, 使用Sentinel注解实现限流
*
* @param orderId
* @return
*/
@SentinelResource(value = "getOrderInfo", blockHandler = "handleFlowQpsException",
fallback = "queryOrderInfo2Fallback")
public String queryOrderInfo2(String orderId) {
// 模拟接口运行时抛出代码异常
if ("000".equals(orderId)) {
throw new RuntimeException();
}
System.out.println("获取订单信息:" + orderId);
return "return OrderInfo :" + orderId;
}
/**
* 订单查询接口抛出限流或降级时的处理逻辑
*
* 注意: 方法参数、返回值要与原函数保持一致
* @return
*/
public String handleFlowQpsException(String orderId, BlockException e) {
e.printStackTrace();
return "handleFlowQpsException for queryOrderInfo2: " + orderId;
}
/**
* 订单查询接口运行时抛出的异常提供fallback处理
*
* 注意: 方法参数、返回值要与原函数保持一致
* @return
*/
public String queryOrderInfo2Fallback(String orderId, Throwable e) {
return "fallback queryOrderInfo2: " + orderId;
}
blockHandler = "handleFlowQpsException"
Sentinelの電流制限/ヒューズおよびその他のエラーを処理するために使用されます。fallback = "queryOrderInfo2Fallback"
インターフェイス内のビジネスコードのすべての例外(ビジネスコードの例外、センチネル電流制限ヒューズの例外など)を処理するために使用されます。
注:上記の2つの処理メソッドのメソッド名とパラメーターは、保護された関数と一致している必要があります。
テスト:
/**
* 限流实现方式二: 注解定义资源
*
* @param orderId
* @return
*/
@RequestMapping("/getOrder2")
@ResponseBody
public String queryOrder3(@RequestParam("orderId") String orderId) {
return orderQueryService.queryOrderInfo2(orderId);
}
テスト結果はここに掲載されておらず、結果も同様です。
2.ヒューズのダウングレード
フロー制御に加えて、呼び出しリンク内の不安定なリソースの融合とダウングレードも、高可用性を確保するための重要な手段の1つです。
通話関係は複雑であるため、通話リンク内の特定のリソースが不安定な場合、最終的にはリクエストの蓄積につながります。Sentinelヒューズのダウングレードは、コールリンク内の特定のリソースが不安定な場合(たとえば、コールタイムアウトや異常率の増加)にこのリソースの呼び出しを制限するため、要求はすぐに失敗し、他のリソースに影響を与えてレベルを引き起こすことを回避します。 。リンクエラー。リソースがダウングレードされると、次のダウングレード時間枠内に、リソースへのすべての呼び出しが自動的に融合されます(デフォルトの動作はthrowですDegradeException
)。
フュージングダウングレードの概要については、Sentinelフュージングダウングレードを参照してください。
以下は、Sentinelの融合とダウングレードのデモを実装するための注釈ベースの方法です。
@Component
@Slf4j
public class GoodsQueryService {
private static final String KEY = "queryGoodsInfo2";
/**
* 模拟商品查询接口
*
* @param spuId
* @return
*/
@SentinelResource(value = KEY, blockHandler = "blockHandlerMethod", fallback = "queryGoodsInfoFallback")
public String queryGoodsInfo(String spuId) {
// 模拟调用服务出现异常
if ("0".equals(spuId)) {
throw new RuntimeException();
}
return "query goodsinfo success, " + spuId;
}
public String blockHandlerMethod(String spuId, BlockException e) {
log.warn("queryGoodsInfo222 blockHandler", e.toString());
return "queryGoodsInfo error, blockHandlerMethod res: " + spuId;
}
public String queryGoodsInfoFallback(String spuId, Throwable e) {
log.warn("queryGoodsInfo222 fallback", e.toString());
return "queryGoodsInfo error, return fallback res: " + spuId;
}
@PostConstruct
public void initDegradeRule() {
List<DegradeRule> rules = new ArrayList<>();
DegradeRule rule = new DegradeRule();
rule.setResource(KEY);
// 80s内调用接口出现异常次数超过5的时候, 进行熔断
rule.setCount(5);
rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);
rule.setTimeWindow(80);
rules.add(rule);
DegradeRuleManager.loadRules(rules);
}
}
// 测试类
@Controller
@RequestMapping("goods")
public class GoodsController {
@Autowired
private GoodsQueryService goodsQueryService;
@RequestMapping("/queryGoodsInfo")
@ResponseBody
public String queryGoodsInfo(@RequestParam("spuId") String spuId) {
String res = goodsQueryService.queryGoodsInfo(spuId);
return res;
}
}
三、コンソールの使用
Sentinelは、マシンの検出、ヘルス管理、監視(単一のマシンとクラスター)、ルール管理、およびプッシュ機能を提供する軽量のオープンソースコンソールを提供します。
主な機能は次のとおりです。
- マシンリストとヘルスステータスを確認してください。
- モニター;
- ルール管理とプッシュ。
- 認証
1.Sentinelコンソールを起動します
コンソールを起動する方法を参照してください:コンソールを起動します
開始方法:
(1)コマンドでjarパッケージをダウンロードします
対応するバージョンのダッシュボードjarパッケージをhttps://github.com/alibaba/Sentinel/releasesからダウンロードし、jarが配置されているディレクトリを入力してから、javaコマンドを使用してjarパッケージを実行します。
java -Dserver.port=8080 \
-Dcsp.sentinel.dashboard.server=localhost:8080 \
-jar target/sentinel-dashboard.jar
(2)sentinelソースコード全体をgit cloneし、sentinel-dashboardモジュールに入り、mvn clean package
packagesコマンドを実行します。実行可能なfat jarパッケージを生成し、コンソールを起動し、url:とlocalhost:8080
入力して、メインページに入ります。
2.クライアントアクセス(コンソールへのSpring Bootプロジェクトアクセス)
コンソールモジュールを起動した後、コンソールページはすべて空であり、クライアントに接続する必要があります。
(1)最初に、コンソールと通信するjarパッケージをインポートします。
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-transport-simple-http</artifactId>
<version>${sentinel.version}</version>
</dependency>
(2)JVM起動パラメーターを構成します。
-Dproject.name=sentinel-demo -Dcsp.sentinel.dashboard.server=127.0.0.1:8080 -Dcsp.sentinel.api.port=8719
アプリケーションを起動します。
注:アプリケーションには、電流制限と劣化をトリガーするための初期化コードが必要です。
このデモのhttp://localhost:8083/order/getOrder1?orderId=123
インターフェースは複数回実行され、電流制限操作がトリガーされます。この時点で、コンソールに移動します。
ご覧のとおり、getOrderInfoインターフェイスが現在制限されている回数。
4.コンソールの使用
コードでのハードコーディングに加えて、Sentinelの電流制限およびヒューズ機能を使用する場合は、コンソールから直接インターフェイスを大まかに制限してヒューズすることもできます。
/**
* 代码不加任何限流 熔断
* @return
*/
@RequestMapping("/test")
@ResponseBody
@SentinelResource("test")
public String test() {
return "test";
}
http://localhost:8083/goods/test
インターフェイスアクションを実行した後、ページのクラスターポイントリンクでインターフェイスがカウントされていることがわかります。
[フロー制御]をクリックして、フロー制御ルールをインターフェイスに追加します。構成は次のとおりです。
[追加]をクリックした後、
再度インターフェースを実行してhttp://localhost:8083/goods/test
ください。QPSが2を超えると、インターフェースが異常に戻り、フロー制御効果が得られます。
もちろん、コンソールフロー制御ルールとダウングレードルールの使用法はまだたくさんあります。それらの使用方法については、公式ドキュメントを参照してください。
PS
コンソールにアクセスする過程で、コンソールは常にエラーを報告することがわかりました。
2019-11-30 20:42:23.338 ERROR 5317 --- [pool-2-thread-1] c.a.c.s.dashboard.metric.MetricFetcher : Failed to fetch metric from <http://10.200.183.30:8721/metric?startTime=1575117735000&endTime=1575117741000&refetch=false> (ConnectionException: Connection refused)
エラーの原因は、クライアントデータを収集するときにコンソールhttp://10.200.183.30:8721
がIPアドレスから接続できないことです。
後で、プロキシがオンになっていることがわかりました。プロキシをオフにした後は正常でした。
参照:
公式ドキュメント:https://github.com/alibaba/Sentinel/wiki
リファレンスブログ:https://www.jianshu.com/p/c47dfd25eeee
この記事のコード:https://github.com/nomico271/sentinel-demo/tree/master/Ch1_SentinelDemo