この記事では、主にマイクロサービス コンポーネントの Hystrix によるスレッド プールの分離とセマフォの分離の実装について紹介します。
目次
1.スレッドプールの分離
1.1. スレッドプール分離の概要
マイクロサービスでは、すべてのインターフェイスが同じスレッド プールで実行されている場合、インターフェイスの 1 つに大量の要求があり、このインターフェイスを処理できない場合、この時点でサービスがリソースを使い果たし、サービス全体がクラッシュします。したがって、この問題を解決するために、Hystrix はスレッド プール分離スキームを提案しました。これは、異なるインターフェイスを異なるスレッド プールに配置して管理し、異なるスレッド プールが互いに干渉しないようにすることで、スレッド プールの 1 つに障害が発生した場合でも、他のスレッド プールに影響を与えないため、サービスがクラッシュする可能性が低くなります。
スレッド プール分離はサービス クラッシュの問題を解決しますが、スレッドの作成と破棄がシステム リソースを消費する必要があるという問題ももたらします.スレッド プール分離を使用すると、このマイクロサービスの要求がますます大きくなると、.対応するスレッドがますます作成され、スレッドの切り替えが非常に頻繁になり、システムのパフォーマンスが低下します。スレッド プールの分離は、分離されたインスタンスが少ないシナリオに適しています。
1.2. スレッドプール分離の実現
(1) 依存関係を導入する
<!--hystrix 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
(2) サービス層のコードを書く
サービス サービス レイヤーでは、[@HystrixCommand] アノテーションを使用して、スレッド プールの分離を有効にする必要があるメソッドをマークします。
package com.gitcode.hystrix.service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;
/**
* @version 1.0.0
* @Date: 2023/4/9 19:49
* @Copyright (C) ZhuYouBin
* @Description:
*/
@Service
public class HystrixThreadService {
@HystrixCommand(
// 命令key,默认是当前方法名称
commandKey = "firstCommandKey",
// 线程池分组的key
groupKey = "queryList-thread-pool",
// 线程池的key,可以和 groupKey 设置相同
threadPoolKey = "queryList-thread-pool",
// 设置 hystrix 命令的属性
commandProperties = {
// 设置线程池隔离的超时时间,默认是1000ms
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
},
// 设置线程池的属性
threadPoolProperties = {
// 核心线程大小
@HystrixProperty(name = "coreSize", value = "4"),
// 队列大小
@HystrixProperty(name = "maxQueueSize", value = "100"),
// 存活时间,默认是 1 分钟,单位是分钟
@HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
// 超出队列执行拒绝策略的阈值
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "100"),
},
// 设置快速失败时候调用的方法,可以写,也可以不写,写了就会执行快速失败,不写就阻塞等待
fallbackMethod = "fallbackDemo"
)
public String queryList() {
// TODO 这里模拟调用其他微服务
try {
Thread.sleep(6000);
System.out.println("微服务调用成功:" + Thread.currentThread().getName());
} catch (Exception e) {}
return "success";
}
@HystrixCommand(
// 命令key,默认是当前方法名称
commandKey = "secondCommandKey",
// 线程池分组的key
groupKey = "getDataById-thread-pool",
// 线程池的key,可以和 groupKey 设置相同
threadPoolKey = "getDataById-thread-pool",
// 设置 hystrix 命令的属性
commandProperties = {
// 设置线程池隔离的超时时间,默认是1000ms
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000")
},
// 设置线程池的属性
threadPoolProperties = {
// 核心线程大小
@HystrixProperty(name = "coreSize", value = "2"),
// 队列大小
@HystrixProperty(name = "maxQueueSize", value = "100"),
// 存活时间,默认是 1 分钟,单位是分钟
@HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
// 超出队列执行拒绝策略的阈值
@HystrixProperty(name = "queueSizeRejectionThreshold", value = "100"),
}
)
public String getDataById() {
// TODO 这里模拟调用其他微服务
System.out.println("微服务调用成功:" + Thread.currentThread().getName());
return "success";
}
public String fallbackDemo() {
return "接口调用失败,请稍后重试!";
}
}
(3)コントローラー層のコードを書く
package com.gitcode.hystrix.controller;
import com.gitcode.hystrix.service.HystrixThreadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @version 1.0.0
* @Date: 2023/4/9 19:47
* @Copyright (C) ZhuYouBin
* @Description: Hystrix 线程池隔离
*/
@RestController
@RequestMapping("/hystrix/thread")
public class HystrixThreadController {
@Autowired
private HystrixThreadService hystrixThreadService;
@GetMapping("/queryList")
public String queryList() {
return hystrixThreadService.queryList();
}
@GetMapping("/getDataById")
public String getDataById() {
return hystrixThreadService.getDataById();
}
}
(4) テストを実行する
アプリケーションを起動すると、ブラウザが 2 つのインターフェイスにアクセスします。
2. セマフォ分離
2.1. セマフォ分離の紹介
スレッド プールの分離を使用すると、スレッドが多すぎてシステムのパフォーマンスが低下する可能性があるため、この問題を解決するために、Hystrix はセマフォの分離を提案しています。セマフォ分離は、同期ブロックと待機の考え方を採用しています. これは、同時にアクセスできるリクエストの最大数を示すために使用されるセマフォを設定します. システムに到着するリクエストの数がこのセマフォを超えると,超過したリクエストはブロックされた状態になるか、または高速フェイル メカニズムを直接採用してエラー メッセージを返します。
セマフォ分離は新しいスレッドを生成しないため、多数のスレッド間での切り替えはありませんが、セマフォ分離には欠点もあり、タイムアウト設定をサポートしていないため、ネットワーク以外の要求に適しています。
2.2. セマフォ分離の実現
(1) 依存関係を導入する
<!--hystrix 依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
(2) サービス層のコードを書く
セマフォ分離にも [@HystrixCommand] の注釈が付けられており、指定された分離戦略は [セマフォ分離] です。
package com.gitcode.hystrix.service;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;
/**
* @version 1.0.0
* @Date: 2023/4/9 19:49
* @Copyright (C) ZhuYouBin
* @Description: 信号量隔离
*/
@Service
public class HystrixSemaphoreService {
@HystrixCommand(
// 设置 hystrix 命令的属性
commandProperties = {
// 设置线程池隔离的超时时间,默认是1000ms
@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "5000"),
// 设置隔离策略是【信号量隔离】,默认是线程池隔离
@HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE"),
// 设置信号量最大请求数, 超过最大信号量数量,如果写了 fallbackMethod 属性,则会调用快速失败方法
@HystrixProperty(name = "execution.isolation.semaphore.maxConcurrentRequests", value = "4")
},
// 设置快速失败时候调用的方法,可以写,也可以不写,写了就会执行快速失败,不写就阻塞等待
fallbackMethod = "fallbackDemo"
)
public String queryList() {
// TODO 这里模拟调用其他微服务
System.out.println("微服务调用成功:" + Thread.currentThread().getName());
return "success";
}
public String fallbackDemo() {
System.out.println("接口调用失败,请稍后重试!");
return "接口调用失败,请稍后重试!";
}
}
(3)コントローラー層のコードを書く
package com.gitcode.hystrix.controller;
import com.gitcode.hystrix.service.HystrixSemaphoreService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @version 1.0.0
* @Date: 2023/4/9 19:47
* @Copyright (C) ZhuYouBin
* @Description: Hystrix 信号量隔离
*/
@RestController
@RequestMapping("/hystrix/semaphore")
public class HystrixSemaphoreController {
@Autowired
private HystrixSemaphoreService hystrixSemaphoreService;
@GetMapping("/queryList")
public String queryList() {
return hystrixSemaphoreService.queryList();
}
}
(4) テストを実行する
アプリケーションを起動し、jemeter を使用して同時リクエストをシミュレートし、コンソール入力ログを表示します。
これまでのところ、Hystrix はスレッド プール分離とセマフォ分離を導入しています。
以上で今回の記事は終了ですが、主にマイクロサービスコンポーネントのHystrixによるスレッドプール分離とセマフォ分離の実装を紹介しました。