微服務:SpringCloud 比hystrix牛的Sentinel(國人的驕傲!)

一、簡介

隨着微服務的流行,服務和服務之間的穩定性變得越來越重要。Sentinel 以流量爲切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。
 
Sentinel 具有以下特徵:
  • 豐富的應用場景Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的範圍)、消息削峯填谷、集羣流量控制、實時熔斷下游不可用應用等。
  •  
    完備的實時監控Sentinel 同時提供實時的監控功能。您可以在控制檯中看到接入應用的單臺機器秒級數據,甚至 500 臺以下規模的集羣的彙總運行情況。
  •  
    廣泛的開源生態Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 SpringCloud、DubbogRPC 的整合。您只需要引入相應的依賴並進行簡單的配置即可快速地接入Sentinel。
  •  
    完善的 SPI 擴展點Sentinel 提供簡單易用、完善的 SPI 擴展接口。您可以通過實現擴展接口來快速地定製邏輯。例如定製規則管理、適配動態數據源等。
 
SentinelHystrix的區別:
 
有關的名詞:
 
Sentinel 可以簡單的分爲 Sentinel 核心庫和 Dashboard。核心庫不依賴 Dashboard,但是結合Dashboard 可以取得最好的效果。
 
使用 Sentinel 來進行熔斷保護,主要分爲幾個步驟:
(1)定義資源
(2)定義規則
(3)檢驗規則是否生效
 
資源:可以是任何東西,一個服務,服務裏的方法,甚至是一段代碼。
 
規則Sentinel 支持以下幾種規則:流量控制規則、熔斷降級規則、系統保護規則、來源訪問控制規則
和 熱點參數規則。Sentinel 的所有規則都可以在內存態中動態地查詢及修改,修改之後立即生效 。
 
先把可能需要保護的資源定義好,之後再配置規則。也可以理解爲,只要有了資源,我們就可以在任何時候靈活地定義各種流量控制規則。在編碼的時候,只需要考慮這個代碼是否需要保護,如果需要保護,就將之定義爲一個資源。
 
下載(您可以從官方網站中下載最新版本的控制檯 jar 包):

https://github.com/alibaba/Sentinel/releases/download/1.6.3/sentinel-dashboard-1.6.3.jar

java -Dserver.port=9090 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.6.3.jar
其中 -Dserver.port=8080 用於指定 Sentinel 控制檯端口爲 8080
 
Sentinel 1.6.0 起,Sentinel 控制檯引入基本的登錄功能,默認用戶名和密碼都是 sentinel
 
注意:啓動 Sentinel 控制檯需要 JDK 版本爲 1.8 及以上版本。
 
 
啓動成功!!!
 
瀏覽器輸入localhost:9090。
 
登陸之後:
 

 

二、微服務註冊到sentinel

基礎的項目目錄。
 
首先父工程需要引入:
 <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.1.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

feign和rest子工程引入:

   <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>

配置文件放入:

spring:
  cloud:
    sentinel:
      transport:
        dashboard: localhost:9090   #sentinel控制檯的請求地址

分別啓動兩個子項目一個是9003端口,一個是9004。註冊中心、以及消費者。

先分別訪問兩個接口:

之後刷新:

就出來了。對應的信息。

三、配置rest資源保護(熔斷降級)

修改rest的order-service

package cn.itcast.order.controller;

import cn.itcast.order.entity.Product;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
@RequestMapping("/order")
public class OrderController {

	@Autowired
	private RestTemplate restTemplate;

	/**
	 * @SentinelResource
	 *      blockHandler : 聲明熔斷時調用的降級方法
	 *      fallback : 拋出異常執行的降級方法
	 *      value : 自定義的資源名稱
	 *          * 不設置:當前全類名.方法名
	 */
	@SentinelResource(value="orderFindById",blockHandler = "orderBlockHandler",fallback = "orderFallback")
	@RequestMapping(value = "/buy/{id}",method = RequestMethod.GET)
	public Product findById(@PathVariable Long id) {
		if(id != 1) {
			throw new RuntimeException("錯誤");
		}
		return restTemplate.getForObject("http://service-product/product/1",Product.class);
	}


	/**
	 * 定義降級邏輯
	 *  hystrix和sentinel
	 *      熔斷執行的降級方法
	 *      拋出異常執行的降級方法
	 */
	public Product orderBlockHandler(Long id) {
		Product product = new Product();
		product.setProductName("觸發熔斷的降級方法");
		return product;
	}

	public Product orderFallback(Long id) {
		Product product = new Product();
		product.setProductName("拋出異常執行的降級方法");
		return product;
	}

}

這裏我們有兩個方法,分別是熔斷執行的降級方法,和拋出異常執行的降級方法。在hystrix中這個是不區分的,但是在sentinel是區分開的。

配置降級規則:

輸入:

過5s再訪問就可以了。這種全都是fallback的降級處理。其他處理看錶:
 

 

四、加載本地配置和另一種配置

大家有沒有發現,如果我們重啓項目之後,再sentinel中配置的東西就都沒了。我們可以搞一個本地配置。

寫一個json

[
  {
    "resource": "orderFindById",
    "controlBehavior": 0,
    "count": 1,
    "grade": 1,
    "limitApp": "default",
    "strategy": 0
  }
]
  •  resource:資源名,即限流規則的作用對象
  • count: 限流閾值
  • grade: 限流閾值類型(QPS 或併發線程數)
  • limitApp: 流控針對的調用來源,若爲 default 則不區分調用來源
  • strategy: 調用關係限流策略
  • controlBehavior: 流量控制效果(直接拒絕、Warm Up、勻速排隊)

然後在配置文件中加入,就可以了

cloud:
    sentinel:
      datasource:
        ds1:
          file:
            file: classpath:flowrule.json
            data-type: json
            rule-type: flow
另一種配置rest方法:
 
定義一個類:
package cn.itcast.order.exception;

import cn.itcast.order.entity.Product;
import com.alibaba.cloud.sentinel.rest.SentinelClientHttpResponse;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSON;
import feign.Feign;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;

public class ExceptionUtils {

	/**
	 * 靜態方法
	 *      返回值: SentinelClientHttpResponse
	 *      參數 : request , byte[] , clientRquestExcetion , blockException
	 */
	//限流熔斷業務邏輯
	public static SentinelClientHttpResponse handleBlock(HttpRequest request, byte[] body, ClientHttpRequestExecution execution, BlockException ex) {
		Product product = new Product();
		product.setProductName("限流熔斷");
		return new SentinelClientHttpResponse(JSON.toJSONString(product));
	}

	//異常降級業務邏輯
	public static SentinelClientHttpResponse handleFallback(HttpRequest request, byte[] body,
		ClientHttpRequestExecution execution, BlockException ex) {
		Product product = new Product();
		product.setProductName("異常降級");
		return new SentinelClientHttpResponse(JSON.toJSONString(product));
	}

}

啓動類加入:

package cn.itcast.order;

import cn.itcast.order.exception.ExceptionUtils;
import com.alibaba.cloud.sentinel.annotation.SentinelRestTemplate;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EntityScan("cn.itcast.order.entity")
public class RestOrderApplication {

	/**
	 * sentinel支持對restTemplate的服務調用使用sentinel方法.在構造
	 *  RestTemplate對象的時候,只需要加載@SentinelRestTemplate即可
	 *
	 *  資源名:
	 *       httpmethod:schema://host:port/path :協議、主機、端口和路徑
	 *       httpmethod:schema://host:port :協議、主機和端口
	 *
	 *  @SentinelRestTemplate:
	 *    異常降級
	 *      fallback      : 降級方法
	 *      fallbackClass : 降級配置類
	 *    限流熔斷
	 *      blockHandler
	 *      blockHandlerClass
	 */

	@LoadBalanced
	@Bean
	@SentinelRestTemplate(fallbackClass = ExceptionUtils.class,fallback = "handleFallback",
		blockHandler = "handleBlock" ,blockHandlerClass = ExceptionUtils.class
	)
	public RestTemplate restTemplate() {
		return new RestTemplate();
	}

	public static void main(String[] args) {
		SpringApplication.run(RestOrderApplication.class,args);
	}
}

之後就不需要之前 @SentinelResource(value="orderFindById",blockHandler = "orderBlockHandler",fallback = "orderFallback") 的配置了。

配置sentinel

配置feign組件的熔斷降級:
 
實際上什麼都不用變,就將添加依賴和配置文件修改爲支持sentinel就可以了
#激活sentinel的支持
feign:
  sentinel:
    enabled: true

 
 
 
 
源碼:[email protected]:Zesystem/springclouddemosentinel.git
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章