<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      springcloud 整合sentinel

      一、參考官網:Sentinel · alibaba/spring-cloud-alibaba Wiki · GitHub

      1. 搭建sentinel Dashborad

                1. 下載jar包: Releases · alibaba/Sentinel (github.com)

                2. 啟動:java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard.jar

               3. 如果8080端口沖突,就更改端口

      2. springcloud項目接入:

         1.引入依賴:

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

        2.在application.yml中配置:  

      spring:
        cloud:
          sentinel:
            transport:
              port: 8719
              dashboard: localhost:8080

      隨便訪問Controller:

       

      點擊流控:配置流控規則:每秒只允許一個請求

       請求超過限制報錯:

       3. 自定義報錯:

      /**
       * author: yangxiaohui
       * date:   2023/8/7
       */
      @Component
      public class SentinelBlockExceptionHandler implements BlockExceptionHandler {
          @Override
          public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws Exception {
              httpServletResponse.setCharacterEncoding("utf-8");
              JSONObject jsonObject = new JSONObject();
              jsonObject.put("ErrorCode","500");
              jsonObject.put("Msg","To Many Request");
              httpServletResponse.getWriter().write(JSON.toJSONString(jsonObject));
      
          }
      }

       源碼分析:sentinel為何能夠對http請求進行限流以及為何能自定義返回對象:(省略部分代碼)

      public abstract class AbstractSentinelInterceptor implements HandlerInterceptor {
          
          @Override
          public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
              throws Exception {
              try {
               
                  String origin = parseOrigin(request);
                  String contextName = getContextName(request);
                  ContextUtil.enter(contextName, origin);
             //sentinel 限流核心代碼,在這里不分析 如果限流不通過就會拋異常BlockException Entry entry
      = SphU.entry(resourceName, ResourceTypeConstants.COMMON_WEB, EntryType.IN); request.setAttribute(baseWebMvcConfig.getRequestAttributeName(), entry);
      return true; } catch (BlockException e) { try { handleBlockException(request, response, e); //限流失敗的返回值 } finally { ContextUtil.exit(); } return false; } } protected void handleBlockException(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception { if (baseWebMvcConfig.getBlockExceptionHandler() != null) { //限流失敗最終是交給 BaseWebMvcConfig的一個接口處理 baseWebMvcConfig.getBlockExceptionHandler().handle(request, response, e); } else { // Throw BlockException directly. Users need to handle it in Spring global exception handler. throw e; } } }

      通過源碼分析,如果了解過springMvc源碼可以知道,要攔截請求只要定義一個攔截器HandlerInterceptor 即可,在攔截的方法里,根據請求路徑,校驗請求有沒達到限流的要求,達到就拋異常,捕捉到異常后,在異常里面處理響應邏輯:

      之后我們再看看SentinelWebAutoConfiguration這個配置類:

      @Configuration(
          proxyBeanMethods = false
      )
      @ConditionalOnWebApplication(
          type = Type.SERVLET
      )
      @ConditionalOnProperty(
          name = {"spring.cloud.sentinel.enabled"},
          matchIfMissing = true
      )
      @ConditionalOnClass({SentinelWebInterceptor.class})
      @EnableConfigurationProperties({SentinelProperties.class})
      public class SentinelWebAutoConfiguration implements WebMvcConfigurer {
          private static final Logger log = LoggerFactory.getLogger(SentinelWebAutoConfiguration.class);
          @Autowired
          private SentinelProperties properties;
          @Autowired
          private Optional<UrlCleaner> urlCleanerOptional;
          @Autowired
          private Optional<BlockExceptionHandler> blockExceptionHandlerOptional;
          @Autowired
          private Optional<RequestOriginParser> requestOriginParserOptional;
          @Autowired
          private Optional<SentinelWebInterceptor> sentinelWebInterceptorOptional;
      
          public SentinelWebAutoConfiguration() {
          }
        //將攔截器也就是SentinelWebInterceptor(繼承了AbstractSentinelInterceptor)注冊到Springmvc中
          public void addInterceptors(InterceptorRegistry registry) {
              if (this.sentinelWebInterceptorOptional.isPresent()) {
                  Filter filterConfig = this.properties.getFilter();
                  registry.addInterceptor((HandlerInterceptor)this.sentinelWebInterceptorOptional.get()).order(filterConfig.getOrder()).addPathPatterns(filterConfig.getUrlPatterns());
                  log.info("[Sentinel Starter] register SentinelWebInterceptor with urlPatterns: {}.", filterConfig.getUrlPatterns());
              }
          }
      
          @Bean
          @ConditionalOnProperty(
              name = {"spring.cloud.sentinel.filter.enabled"},
              matchIfMissing = true
          )
        //攔截器
      public SentinelWebInterceptor sentinelWebInterceptor(SentinelWebMvcConfig sentinelWebMvcConfig) { return new SentinelWebInterceptor(sentinelWebMvcConfig); } @Bean @ConditionalOnProperty( name = {"spring.cloud.sentinel.filter.enabled"}, matchIfMissing = true )
      //SentinelWebMvcConfig 繼承了BaseWebMvcConfig
      public SentinelWebMvcConfig sentinelWebMvcConfig() { SentinelWebMvcConfig sentinelWebMvcConfig = new SentinelWebMvcConfig(); sentinelWebMvcConfig.setHttpMethodSpecify(this.properties.getHttpMethodSpecify()); sentinelWebMvcConfig.setWebContextUnify(this.properties.getWebContextUnify()); if (this.blockExceptionHandlerOptional.isPresent()) { //如果容器中提供了限流異常處理器,就用提供的 this.blockExceptionHandlerOptional.ifPresent(sentinelWebMvcConfig::setBlockExceptionHandler); } else if (StringUtils.hasText(this.properties.getBlockPage())) { //如果提供了限流異常跳轉頁面 sentinelWebMvcConfig.setBlockExceptionHandler((request, response, e) -> { response.sendRedirect(this.properties.getBlockPage()); }); } else { //都沒提供就用默認的 sentinelWebMvcConfig.setBlockExceptionHandler(new DefaultBlockExceptionHandler()); } this.urlCleanerOptional.ifPresent(sentinelWebMvcConfig::setUrlCleaner); this.requestOriginParserOptional.ifPresent(sentinelWebMvcConfig::setOriginParser); return sentinelWebMvcConfig; } }

      通過代碼分析,如果沒有提供異常處理器,就會有個默認的異常處理,提供了,就用提供的,我們看看默認的 DefaultBlockExceptionHandler

       所以,我們自定義的異常處理器可以替換默認的異常處理器

      4. 前面分析,sentinel整合springcloud默認會對http請求進行攔截,本質是springmvc的攔截器導致的,那么如何對feign進行限流配置呢?

          1. 在application.yaml中開啟配置:

      feign:
        sentinel:
          enabled: true

         2. 簡單demo示例

      @FeignClient(name = "service-provider", fallback = EchoServiceFallback.class, configuration = FeignConfiguration.class)
      public interface EchoService {
          @RequestMapping(value = "/echo/{str}", method = RequestMethod.GET)
          String echo(@PathVariable("str") String str);
      }
      
      class FeignConfiguration {
          @Bean
          public EchoServiceFallback echoServiceFallback() {
              return new EchoServiceFallback();
          }
      }
      
      class EchoServiceFallback implements EchoService {
          @Override
          public String echo(@PathVariable("str") String str) {
              return "echo fallback";
          }
      }

      5.如果我們想攔截非http請求的方法:基于 @SentinelResource注解實現攔截

      /**
       * author: yangxiaohui
       * date:   2023/8/7
       */
      @Service
      public class TestService {
      
          @SentinelResource(value = "sayHello",blockHandler = "blockHandler",blockHandlerClass ={BlockClass.class} )
          public String sayHello(String name) {
              return "Hello, " + name;
          }
      
          public static class BlockClass{
              //這個方法必須是靜態方法
              public static String blockHandler(String name, BlockException blockException){
      
                  System.out.println("被阻塞了。。。。。。。。。。。。");
      
                  return "haha";
      
              }
      
          }
      }

      實現原理是AOP:

      @Aspect
      public class SentinelResourceAspect extends AbstractSentinelAspectSupport {
      
          @Pointcut("@annotation(com.alibaba.csp.sentinel.annotation.SentinelResource)")
          public void sentinelResourceAnnotationPointcut() {
          }
      
          @Around("sentinelResourceAnnotationPointcut()")
          public Object invokeResourceWithSentinel(ProceedingJoinPoint pjp) throws Throwable {
              Method originMethod = resolveMethod(pjp);
      
              SentinelResource annotation = originMethod.getAnnotation(SentinelResource.class);
              if (annotation == null) {
                  // Should not go through here.
                  throw new IllegalStateException("Wrong state for SentinelResource annotation");
              }
              String resourceName = getResourceName(annotation.value(), originMethod);
              EntryType entryType = annotation.entryType();
              int resourceType = annotation.resourceType();
              Entry entry = null;
              try {
                  entry = SphU.entry(resourceName, resourceType, entryType, pjp.getArgs());
                  Object result = pjp.proceed();
                  return result;
              } catch (BlockException ex) {
                  return handleBlockException(pjp, annotation, ex);
              } catch (Throwable ex) {
                  Class<? extends Throwable>[] exceptionsToIgnore = annotation.exceptionsToIgnore();
                  // The ignore list will be checked first.
                  if (exceptionsToIgnore.length > 0 && exceptionBelongsTo(ex, exceptionsToIgnore)) {
                      throw ex;
                  }
                  if (exceptionBelongsTo(ex, annotation.exceptionsToTrace())) {
                      traceException(ex);
                      return handleFallback(pjp, annotation, ex);
                  }
      
                  // No fallback function can handle the exception, so throw it out.
                  throw ex;
              } finally {
                  if (entry != null) {
                      entry.exit(1, pjp.getArgs());
                  }
              }
          }
      }

       6. gateWay網關配置:

           1.引入依賴:

         

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

           2. 配置yml

      spring:
        cloud:
          sentinel:
            filter:
              enabled: false
            transport:
              port: 8719
              dashboard: localhost:8080       
        

      調用后:

       

         3. 限流失敗后,返回默認錯誤

      /**
       * author: yangxiaohui
       * date:   2023/8/7
       */
      @Configuration
      public class SentinelGatewayConfig {
          public SentinelGatewayConfig() {
              GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
                  @Override
                  public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                      JSONObject jsonObject = new JSONObject();
                      jsonObject.put("ErrorCode","500");
                      jsonObject.put("Msg","To Many Request");
                      return ServerResponse.ok().body(Mono.just(JSON.toJSONString(jsonObject)), String.class);
                  }
              });
          }
      }

       7.前面各種框架的整合,核心代碼,其實還是:

      try (Entry entry = SphU.entry("HelloWorld")) {
          // Your business logic here.
          System.out.println("hello world");
      } catch (BlockException e) {
          // Handle rejected request.
          e.printStackTrace();
      }

       

       源碼大概:

       

       用官網的一張原理圖展示:

       具體源碼過程

       8.持久化流控規則 使用nacos 

           1.引入依賴 在自己項目中引入

        <dependency>
                  <groupId>com.alibaba.csp</groupId>
                  <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>

            2. 在yaml中配置:這里以流控規則Flow為例,其他的規則如熱點規則等,只要改下名稱、dataId 、rule-type

           

      spring:
        cloud:
          sentinel:
            transport:
              dashboard: localhost:8080
            datasource:
              # 名稱隨意
              flow:
                nacos:
                  server-addr: 192.168.50.161:8848
                  namespace: e5aa487a-9717-4738-8c0a-40cf58bd3a99
                  dataId: sentinel-flow
                  groupId: DEFAULT_GROUP
                  rule-type: flow

      對應nacos的值:

       

       

      規則是一個數組,可以配置多個:

      Flow規則:

       

      [
        {
          // 資源名
          "resource": "/test",
          // 針對來源,若為 default 則不區分調用來源
          "limitApp": "default",
          // 限流閾值類型(1:QPS;0:并發線程數)
          "grade": 1,
          // 閾值
          "count": 1,
          // 是否是集群模式
          "clusterMode": false,
          // 流控效果(0:快速失敗;1:Warm Up(預熱模式);2:排隊等待)
          "controlBehavior": 0,
          // 流控模式(0:直接;1:關聯;2:鏈路)
          "strategy": 0,
          // 預熱時間(秒,預熱模式需要此參數)
          "warmUpPeriodSec": 10,
          // 超時時間(排隊等待模式需要此參數)
          "maxQueueingTimeMs": 500,
          // 關聯資源、入口資源(關聯、鏈路模式)
          "refResource": "ddd"
        }
      ]

       降級規則:

      [
        {
            // 資源名
          "resource": "/test1",
          "limitApp": "default",
          // 熔斷策略(0:慢調用比例,1:異常比率,2:異常計數)
          "grade": 0,
          // 最大RT、比例閾值、異常數
          "count": 200,
          // 慢調用比例閾值,僅慢調用比例模式有效(1.8.0 引入)
          "slowRatioThreshold": 0.2,
          // 最小請求數
          "minRequestAmount": 5,
          // 當單位統計時長(類中默認1000)
          "statIntervalMs": 1000,
          // 熔斷時長
          "timeWindow": 10
        }
      ]

      熱點規則:

      [
        {
            // 資源名
          "resource": "/test1",
          // 限流模式(QPS 模式,不可更改)
          "grade": 1,
          // 參數索引
          "paramIdx": 0,
          // 單機閾值
          "count": 13,
          // 統計窗口時長
          "durationInSec": 6,
          // 是否集群 默認false
          "clusterMode": 默認false,
          // 
          "burstCount": 0,
          // 集群模式配置
          "clusterConfig": {
            // 
            "fallbackToLocalWhenFail": true,
               // 
            "flowId": 2,
            // 
            "sampleCount": 10,
            // 
            "thresholdType": 0,
            // 
            "windowIntervalMs": 1000
          },
          // 流控效果(支持快速失敗和勻速排隊模式)
          "controlBehavior": 0,
          // 
          "limitApp": "default",
          // 
          "maxQueueingTimeMs": 0,
          // 高級選項
          "paramFlowItemList": [
            {
                // 參數類型
              "classType": "int",
                // 限流閾值
              "count": 222,
                // 參數值
              "object": "2"
            }
          ]
        }
      ]

      系統規則:

      [
        {
            // RT
          "avgRt": 1,
          // CPU 使用率
          "highestCpuUsage": -1,
          // LOAD
          "highestSystemLoad": -1,
          // 線程數
          "maxThread": -1,
          // 入口 QPS
          "qps": -1
        }
      ]

      授權規則:

      [
        {
          // 資源名
          "resource": "sentinel_spring_web_context",
            // 流控應用
          "limitApp": "/test",
          // 授權類型(0代表白名單;1代表黑名單。)
          "strategy": 0
        }
      ]

      注意:配置時,去掉上面的注釋,保證json格式正確

      配置多個規則時,在yml中:

      spring:
        cloud:
          sentinel:
            transport:
              dashboard: localhost:8080
            datasource:
              # 名稱隨意
              flow:
                nacos:
                  server-addr: 192.168.50.161:8848
                  namespace: e5aa487a-9717-4738-8c0a-40cf58bd3a99
                  dataId: sentinel-flow
                  groupId: DEFAULT_GROUP
                  rule-type: flow
              #系統規則
              system:
                nacos:
                  server-addr: 192.168.50.161:8848
                  namespace: e5aa487a-9717-4738-8c0a-40cf58bd3a99
                  dataId: sentinel-system
                  groupId: DEFAULT_GROUP
                  rule-type: system

      rule-type 配置表示該數據源中的規則屬于哪種類型的規則(flow, degrade, authority, system, param-flow, gw-flow, gw-api-group)。注意網關流控規則 (GatewayFlowRule) 對應 gw-flow。

       

      posted @ 2023-08-07 10:13  yangxiaohui227  閱讀(1426)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产在线无遮挡免费观看| 久久综合国产精品一区二区| 亚洲精品日韩中文字幕| 国产精品自在线拍国产手机版| 自拍偷自拍亚洲精品播放| 美国又粗又长久久性黄大片| 成人国产片视频在线观看| 国产免费丝袜调教视频| 野外做受三级视频| 又大又粗又硬又爽黄毛少妇| 亚洲人成电影在线天堂色| 欧美精品在线观看视频| 精品国产免费一区二区三区香蕉 | 国产偷人妻精品一区二区在线| 日韩丝袜亚洲国产欧美一区| 亚洲美女被黑人巨大在线播放| 亚洲精品日本一区二区| 国产欧美在线观看一区| 欧洲中文字幕一区二区| 日韩熟女精品一区二区三区 | 亚洲国产精品嫩草影院久久 | 精品人妻码一区二区三区| 亚洲欧洲日产国无高清码图片| 99久久综合精品五月天| 亚洲综合91社区精品福利| 国产黄色看三级三级三级| 免费a级毛片18以上观看精品| 万盛区| 国产精品无码a∨麻豆| 激情综合色综合啪啪五月| 亚洲精品网站在线观看不卡无广告 | 亚洲av成人无网码天堂| 激情综合网激情综合网激情| 精品日韩亚洲AV无码| 边添小泬边狠狠躁视频| 亚洲成av人片天堂网无码| 内射干少妇亚洲69XXX| 不卡乱辈伦在线看中文字幕| 免费无遮挡无码永久在线观看视频| 99精品国产一区二区三区| 欧洲精品一区二区三区久久|