Spring-cloudマイクロサービスアーキテクチャ構築03-Hystrixの理解と構成使用
15969 ワード
1.hystrixの概要
分散型のサービスシステムでは、サービスダウンタイムが発生することはよくあります.hystrixが提供するクライアントのフレックスモード設計は、クライアントを迅速に失敗させ、リモートリソースを保護し、サービス消費の「上流」伝播を防止することができます.
Hystrixライブラリは高度に構成可能であり、開発者が定義した遮断器モードとハッチ壁モードを使用する動作を厳格に制御することができる.開発者は、Hystrix遮断器の構成を変更することで、Hystrixがリモートコールをタイムアウトするまで待つ時間を制御できます.開発者は、Hystrix遮断器がいつブレーキを切るか、Hystrixが遮断器をリセットしようとするかを制御することもできます.
Hystrixを使用すると、開発者はまた、リモート・サービス・コールごとに個別のスレッド・グループを定義し、各スレッド・グループに対応するスレッド数を構成することで、ハッチング・ウォールを微調整することもできます.これにより、開発者は、一部のリモート・リソース・コールが要求量が高いため、リモート・サービス・コールを微調整できます.
クライアントフレックスモード?次の4つの点があります.クライアント負荷等化モードはribbonモジュールによって提供される. 遮断器モード(circuit breaker); クイック失敗モード(fallback); 室壁モード(bulkhead); 次に、Feign-service(Feign結合Hystrix)モジュールとDemo-dervice(前編の基礎サービスモジュール)によってhystixコンポーネントの機能テストと理解を行う.
2.hystrix-serviceモジュール快速構築
注意:本プロジェクトはideaツールを採用して構築する idea自身のspring initializrを使用してプロジェクトの初期化を行い、プロジェクト名は:feign-serviceで、その主なテストはfeignの遠隔呼び出しに基づいて、restTemplateのテストもあります; 初期化完了項目後pomファイルインポート アプリケーションを修正する.ymlファイル、 の構成を追加 bootstrapを修正する.ymlファイル、eureka-configをリンクし、 の構成を追加します.サービス開始クラスの最終変更:
最後に、リモートコールクライアントインタフェースを追加すると、次のようになります.テストインタフェース を追加はこの構成でhystrixを完了し、テスト使用を開始することができ、テストリモートコールのサービスインスタンスはdemo-serviceであり、postmanまたは他のツールを通じて構成が完璧であることを発見することができ、hystrixの具体的な構成と使用について説明します.
3.hystrix返品メカニズムロールバックメカニズムは、バックアップメカニズムとも呼ばれ、サービスコールが到達できない場合、またはサービスコールがタイムアウトに失敗した場合のバックアップ操作です.fallback定義には2つの方法があります: feignの@FeignClientでfallbackプロパティを定義し、c次clientインタフェースを実装するクラスを定義します. @HystrixCommand(fallbackMethod="buildFallbackMethod")方式; サービスコール遅延のメカニズムを使用して、 を処理します.上記のようにtestfeignインタフェースを呼び出すと、乱数が3のときにスレッドのスリープが発生し、hystrixのデフォルトの呼び出しタイムアウト時間を超え、インタフェースはバックグラウンドメソッドbuildFallbacktestFeignの戻り値を返します.
注意:ロールバックメソッドでリモートインタフェースの呼び出しを行う場合も、@HystrixCommandを使用してラップする必要があります.そうしないと、問題が発生して大きな損をします.
4.hystrixスレッドプールの分離とパラメータの微調整スレッドプール分離は、グローバルに設定してもよいし@HystrixCommandに以下のパラメータを格納して構成してもよい.動的構成が必要な場合はaopで構成してもよい.構成パラメータは以下の通りである: .は、メソッドに追加する他、クラス上でクラスのグローバル制御 を行うこともできる.
5.hystrixキャッシュ構成
Hystrixリクエストキャッシュは、一度だけ書き込むと結果が変わらないのではなく、リクエストがControllerに到達するたびにHystrixRequestContextを初期化する必要があります.これまでのキャッシュは存在しませんでした.同じリクエストで結果が同じであることを保証し、同じリクエストでの最初のアクセス後に結果をキャッシュします.キャッシュのライフサイクルは1回のみ要求されます!redisを使用してurlキャッシュを行うモードとは異なります.テストコードは次のとおりです. postmanによるテストコールhttp://localhost:8090/cache/1;demo-serviceサービスは2回応答しており、最初のキャッシュchenが成功し、update後にキャッシュが削除されたことを示しています.テストの過程で出会った問題はすでに注釈されており、読者は自分でテストすることができる.
6.hystrix異常放出処理@HystrixCommandのignoreExceptions属性は無視する異常をHystrixBadRequestExceptionとしてパッケージし、コールバックを実行しない. インタフェースコールhttp://localhost:8090/exception/1サービスは異常を放出し、インタフェースは異常情報を受信する.ignoreExceptions={RuntimeException.class}を削除してインタフェースを再度呼び出すと、buildFallbackTestExceptionロールバックメソッドが実行されていることがわかります.
8.hystrix要求連結
注意:マージメソッド自体を要求するときに高遅延のコマンドは、一般的に遅延の低いサービスに対して遅延時間の合理化と遅延タイムウィンドウ内の同時量を考慮する必要があります.統合を要求するテスト
-呼び出しインタフェースhttp://localhost:8090/collapse/1jmeterなどの同時テストツールを使用してテストできます.上記のコメント情報の結果を返すと、これらのパラメータを設定するには多方面のテストが必要であることを示します.
9.Hystrix ThreadLocalコンテキストの伝達
具体的には、以下の参考ブログを参考にしてもいいし、githubコードをダウンロードしてテストしてもいいです.
注意:ThreadLocalコンテキストの転送を構成した後、hystrixのcacheテストを振り返ってテストしたところ、キャッシュをクリーンアップする機能が失効したことがわかりました.アイデアのあるブロガーがアドバイスをしてくれることを望んでいます.ありがとうございます.
本文githubコードアドレス:私のgithub:spring-cloud基礎モジュール構築---ご指摘を歓迎します
参考博文:SpringCloud(8)Hystrix要求キャッシュのHystrix使用によるThreadLocalコンテキストの伝達
分散型のサービスシステムでは、サービスダウンタイムが発生することはよくあります.hystrixが提供するクライアントのフレックスモード設計は、クライアントを迅速に失敗させ、リモートリソースを保護し、サービス消費の「上流」伝播を防止することができます.
Hystrixライブラリは高度に構成可能であり、開発者が定義した遮断器モードとハッチ壁モードを使用する動作を厳格に制御することができる.開発者は、Hystrix遮断器の構成を変更することで、Hystrixがリモートコールをタイムアウトするまで待つ時間を制御できます.開発者は、Hystrix遮断器がいつブレーキを切るか、Hystrixが遮断器をリセットしようとするかを制御することもできます.
Hystrixを使用すると、開発者はまた、リモート・サービス・コールごとに個別のスレッド・グループを定義し、各スレッド・グループに対応するスレッド数を構成することで、ハッチング・ウォールを微調整することもできます.これにより、開発者は、一部のリモート・リソース・コールが要求量が高いため、リモート・サービス・コールを微調整できます.
クライアントフレックスモード?次の4つの点があります.
2.hystrix-serviceモジュール快速構築
注意:本プロジェクトはideaツールを採用して構築する
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.cloud
spring-cloud-starter-openfeign
org.springframework.cloud
spring-cloud-starter-netflix-hystrix
management:
endpoints:
web:
exposure:
include: "*" # , hystrix.stream
endpoint:
health:
show-details: ALWAYS
# feign
feign:
compression:
request:
enabled: true #
mime-types: text/xml;application/xml;application/json #
min-request-size: 2048 # ,
response:
#
enabled: true
hystrix:
# feign hystrix , feign hystrix
# 。
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
hostname: localhost
preferIpAddress: true
@ServletComponentScan
@EnableFeignClients
@SpringCloudApplication
public class FeignServiceApplication {
public static void main(String[] args) {
SpringApplication.run(FeignServiceApplication.class, args);
}
/**
* feign
* Logger.Level :
* NONE, ( )。
* BASIC, URL 。
* HEADERS, 。
* FULL, , 。
*/
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.HEADERS;
}
/**
* restTemplate
*/
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
最後に、リモートコールクライアントインタフェースを追加すると、次のようになります.
/**
* feign demo-service
* name
* fallback
*/
@FeignClient(value = "demo-service",
// configuration = DisableHystrixConfiguration.class, //
fallback = DemoServiceHystrix.class)
public interface DemoClient {
@GetMapping(value = "/test/hello")
ResultInfo hello();
@GetMapping(value = "/test/{id}",consumes = "application/json")
ResultInfo getTest(@PathVariable("id") Integer id);
@PostMapping(value = "/test/add")
ResultInfo addTest(Test test);
@PutMapping(value = "/test/update")
ResultInfo updateTest(Test test);
@GetMapping(value = "/test/collapse/{id}")
Test collapse(@PathVariable("id") Integer id);
@GetMapping(value = "/test/collapse/findAll")
List collapseFindAll(@RequestParam(value = "ids") List ids);
}
/**
* restTemplate
*/
@Component
public class RestClient {
@Autowired
RestTemplate restTemplate;
@HystrixCommand
public ResultInfo getTest(Integer id){
log.info(">>>>>>>>> restTemplate >>>>>>>>>>>>");
ResponseEntity restExchange =
restTemplate.exchange(
"http://demo-service/test/{id}",
HttpMethod.GET,
null, ResultInfo.class, id);
return restExchange.getBody();
}
}
@Log4j2
@RestController
@RequestMapping("/test")
public class FeignController {
@Autowired
private DemoClient demoClient;
@Autowired
private RestClient restClient;
@HystrixCommand
@GetMapping("/feign/{id}")
public ResultInfo testFeign(@PathVariable("id") Integer id){
log.info(" feign 。。。");
ResultInfo test = demoClient.getTest(id);
log.info(" : " + test);
/**
* hystrix 1
* fallbackMethod
*/
//log.info(" :" + randomlyRunLong() + " ");
return test;
}
@HystrixCommand
@GetMapping("/rest/{id}")
public ResultInfo testRest(@PathVariable("id") Integer id){
log.info(" restTemplate 。。。");
return restClient.getTest(id);
}
3.hystrix返品メカニズム
@HystrixCommand(
// feign
fallbackMethod = "buildFallbacktestFeign",
)
@GetMapping("/feign/{id}")
public ResultInfo testFeign(@PathVariable("id") Integer id){
...
/**
* hystrix 1
* fallbackMethod
*/
log.info(" :" + randomlyRunLong() + " ");
return test;
}
...
/**
* testFeign
* @return
*/
private ResultInfo buildFallbacktestFeign(Integer id){
return ResultUtil.success("testFeign , : " + id );
}
//
private Integer randomlyRunLong(){
Random rand = new Random();
int randomNum = rand.nextInt(3) + 1;
if (randomNum==3) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return randomNum;
}
注意:ロールバックメソッドでリモートインタフェースの呼び出しを行う場合も、@HystrixCommandを使用してラップする必要があります.そうしないと、問題が発生して大きな損をします.
4.hystrixスレッドプールの分離とパラメータの微調整
//
threadPoolKey = "test",
threadPoolProperties = {
@HystrixProperty(name = "coreSize",value="30"),
@HystrixProperty(name="maxQueueSize", value="10")},
//
commandProperties={
// hystrix ,
// @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value="4000"),
// , 10
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold", value="10"),
// requestVolumeThreshold ,
@HystrixProperty(name="circuitBreaker.errorThresholdPercentage", value="75"),
// ,
@HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds", value="7000"),
// 10000ms
@HystrixProperty(name="metrics.rollingStats.timeInMilliseconds", value="15000"),
// timeInMilliseconds , ,cpu
@HystrixProperty(name="metrics.rollingStats.numBuckets", value="5")}
//
@DefaultProperties(
commandProperties={
// , 10
@HystrixProperty(name="circuitBreaker.requestVolumeThreshold", value="10"),
// requestVolumeThreshold ,
@HystrixProperty(name="circuitBreaker.errorThresholdPercentage", value="75")}
)
5.hystrixキャッシュ構成
Hystrixリクエストキャッシュは、一度だけ書き込むと結果が変わらないのではなく、リクエストがControllerに到達するたびにHystrixRequestContextを初期化する必要があります.これまでのキャッシュは存在しませんでした.同じリクエストで結果が同じであることを保証し、同じリクエストでの最初のアクセス後に結果をキャッシュします.キャッシュのライフサイクルは1回のみ要求されます!redisを使用してurlキャッシュを行うモードとは異なります.テストコードは次のとおりです.
@RestController
@RequestMapping("/cache")
public class CacheTestController {
@Autowired
private CacheService cacheService;
@GetMapping("/{id}")
public ResultInfo testCache(@PathVariable("id") Integer id){
//
log.info(" : "+cacheService.testCache(id));
//
log.info(" : "+cacheService.testCache(id));
//
cacheService.updateCache(new Test(id,"wangwu","121"));
// ,
log.info(" : "+cacheService.testCache(id));
//
log.info(" : "+cacheService.testCache(id));
return ResultUtil.success("cache !!!");
}
}
@Service
public class CacheService {
@Autowired
private DemoClient demoClient;
/**
* commandKey
* groupKey
* threadPoolKey
*
* CacheResult
* cacheKeyMethod key @CacheKey()
*
* CacheKey() key ,
* CacheKey("id") Integer id , CacheKey() key
* java.beans.IntrospectionException: Method not found: isId
*
* :
* java.lang.IllegalStateException: Request caching is not available. Maybe you need to initialize the HystrixRequestContext?
*
* : , Controller ,
* HystrixRequestContext , ,
* , , !
* redis url 。
* , HystrixRequestContext 。
*/
@CacheResult(cacheKeyMethod = "getCacheKey")
@HystrixCommand(commandKey = "testCache", groupKey = "CacheTestGroup", threadPoolKey = "CacheTestThreadPool")
public ResultInfo testCache(Integer id){
log.info("test cache 。。。");
return demoClient.getTest(id);
}
/**
* :
* 1、 , ,
* fallbackMethod ;
* 2、 String , :
* com.netflix.hystrix.contrib.javanica.exception.HystrixCachingException:
* return type of cacheKey method must be String.
*/
private String getCacheKey(Integer id){
log.info(" key 。。。");
return String.valueOf(id);
}
@CacheRemove(commandKey = "testCache")
@HystrixCommand(commandKey = "updateCache", groupKey = "CacheTestGroup", threadPoolKey = "CacheTestThreadPool")
public ResultInfo updateCache(@CacheKey("id") Test test){
log.info("update cache 。。。");
return demoClient.updateTest(test);
}
}
6.hystrix異常放出処理
@RestController
@RequestMapping("/exception")
public class ExceptionTestController {
@Autowired
private DemoClient demoClient;
/**
* ignoreExceptions RuntimeException
* HystrixBadRequestException, .
*/
@HystrixCommand(ignoreExceptions = {RuntimeException.class},
fallbackMethod = "buildFallbackTestException")
@GetMapping("/{id}")
public ResultInfo testException(@PathVariable("id") Integer id){
log.info("test exception 。。。");
if (id == 1){
throw new RuntimeException(" ");
}
return demoClient.getTest(id);
}
/**
* testFeign
* @return
*/
private ResultInfo buildFallbackTestException(Integer id){
return ResultUtil.success("testException , : " + id );
}
}
8.hystrix要求連結
注意:マージメソッド自体を要求するときに高遅延のコマンドは、一般的に遅延の低いサービスに対して遅延時間の合理化と遅延タイムウィンドウ内の同時量を考慮する必要があります.
@RestController
@RequestMapping("/collapse")
public class CollapseController {
@Autowired
private CollapseService collapseService;
@GetMapping("/{id}")
public ResultInfo testRest(@PathVariable("id") Integer id){
log.info(" Collapse , : " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
Test test = collapseService.testRest(id);
log.info(" Collapse , : " + LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
/**
* :
* : 2018-10-18T10:40:12.374
* : 2018-10-18T10:40:13.952
* :
* : 2018-10-18T10:43:41.472
* : 2018-10-18T10:43:41.494
*/
return ResultUtil.success(test);
}
}
@Service
public class CollapseService {
@Autowired
private DemoClient demoClient;
@HystrixCollapser(
// batch
batchMethod = "findAll",
collapserProperties = {
// 100ms ,
@HystrixProperty(name = "timerDelayInMilliseconds", value = "1000")
})
public Test testRest(Integer id){
Test test = demoClient.collapse(id);
return test;
}
// batch method must be annotated with HystrixCommand annotation
@HystrixCommand
private List findAll(List ids){
log.info(" findAll Collapse 。。。");
return demoClient.collapseFindAll(ids);
}
}
-呼び出しインタフェースhttp://localhost:8090/collapse/1jmeterなどの同時テストツールを使用してテストできます.上記のコメント情報の結果を返すと、これらのパラメータを設定するには多方面のテストが必要であることを示します.
9.Hystrix ThreadLocalコンテキストの伝達
具体的には、以下の参考ブログを参考にしてもいいし、githubコードをダウンロードしてテストしてもいいです.
注意:ThreadLocalコンテキストの転送を構成した後、hystrixのcacheテストを振り返ってテストしたところ、キャッシュをクリーンアップする機能が失効したことがわかりました.アイデアのあるブロガーがアドバイスをしてくれることを望んでいます.ありがとうございます.
本文githubコードアドレス:私のgithub:spring-cloud基礎モジュール構築---ご指摘を歓迎します
参考博文:SpringCloud(8)Hystrix要求キャッシュのHystrix使用によるThreadLocalコンテキストの伝達