springcloud筆記6——服務降級報警

需求實現的幾個考慮重點:

  • 發生服務降級後向管理員發出警報
  • 考慮集羣環境下需要報警哪臺服務器哪個服務發生了降級
  • 同一個服務降級一個時間段內只發送一次警報,超過這個時間段任然存在再次警報
  • 服務降級發生的觸發與發送短信任務應該是異步的
  • 基於集羣通信和報警時效考慮,使用redis實現,如果將一個降級報警設置了過期時間,沒過期不重發報警,需要考慮熱點緩存問題

實現代碼如下:

1,添加redis依賴

pom文件
    <!--Spring Boot與Redis整合依賴-->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
    </dependency>
    
yml文件
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456

2,修改處理器

    @Autowired
    private StringRedisTemplate template;

    //短信任務放入線程處理
    private ForkJoinPool pool = new ForkJoinPool(5);

    //原有的請求添加HttpServletRequest獲取ip
    @HystrixCommand(fallbackMethod = "getHystrixHandle")
    @GetMapping("/get/{id}")
    public Depart getHandle(@PathVariable("id") int id, HttpServletRequest request) {
        return service.getDepartById(id);
    }

    //服務降級方法發送報警短信
    public Depart getHystrixHandle(@PathVariable("id") int id,
                                   HttpServletRequest request) {
        //指定存放到Redis中的key爲 ip_發生降級的方法名
        String ip = request.getLocalAddr();
        String key = ip + "_getDepartById";
        alarm(key);

        Depart depart = new Depart();
        depart.setId(id);
        depart.setName("no this depart");
        return depart;
    }

    // 降級發生後的報警
    private void alarm(String key) {
        //獲取Redis操作對象
        BoundValueOperations<String, String> ops = template.boundValueOps(key);
        String value = ops.get();
        //redis中不存在降級服務key時才發送短信,每次發送短信設置過期時間,時間到了再次發送
        //redis設置過期時間時必須考慮熱點緩存問題,發送短信但還沒有設置值時會重複進入方法發送短信,這裏使用雙重檢測鎖解決
        if(value == null) {
            synchronized (this) {
                value = ops.get();
                if(value == null) {
                    // 發送短信
                    sendFallbackMsg(key);
                    value = "已發生服務降級";
                    ops.set(value, 10, TimeUnit.SECONDS);
                }
            }
        }
    }

    // 使用線程池實現異步短信發送
    private void sendFallbackMsg(String key) {
        pool.submit(() -> {
            System.out.println("發送服務異常報警短信:" + key);
        });

    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章