1. 程式人生 > 其它 >Hystrix叢集及叢集監控turbine

Hystrix叢集及叢集監控turbine

技術標籤:ribbonspring cloud

目錄

Hystrix叢集及監控turbine

前面Dashboard演示的僅僅是單機服務監控,實際專案基本都是叢集,所以這裡叢集監控用的是turbine。

turbine是基於Dashboard的。

先搞個叢集;
再microservice-student-provider-hystrix-1004專案的基礎上再搞一個microservice-student-provider-hystrix-1005

程式碼和配置都複製一份,然後修改幾個地方

---
server:
  port: 1004
  context-path: /
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
    username: xiaoyang
    password: 123
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  application:
    name: microservice-student
  profiles: provider-hystrix-1004

eureka:
  instance:
    hostname: localhost
    appname: microservice-student
    instance-id: microservice-student:1004
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://eureka2001.xiaoyang.com:2001/eureka/,http://eureka2002.xiaoyang.com:2002/eureka/,http://eureka2003.xiaoyang.com:2003/eureka/

info:
  groupId: com.xiaoyang.testSpringcloud
  artifactId: microservice-student-provider-hystrix-1004
  version: 1.0-SNAPSHOT
  userName: http://xiaoyang.com
  phone: 123456

---
server:
  port: 1005
  context-path: /
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
    username: xiaoyang
    password: 123
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  application:
    name: microservice-student
  profiles: provider-hystrix-1005

eureka:
  instance:
    hostname: localhost
    appname: microservice-student
    instance-id: microservice-student:1005
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://eureka2001.xiaoyang.com:2001/eureka/,http://eureka2002.xiaoyang.com:2002/eureka/,http://eureka2003.xiaoyang.com:2003/eureka/

info:
  groupId: com.xiaoyang.testSpringcloud
  artifactId: microservice-student-provider-hystrix-1005
  version: 1.0-SNAPSHOT
  userName: http://xiaoyang.com
  phone: 123456
---
server:
  port: 1006
  context-path: /
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8
    username: xiaoyang
    password: 123
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  application:
    name: microservice-student
  profiles: provider-hystrix-1006

eureka:
  instance:
    hostname: localhost
    appname: microservice-student
    instance-id: microservice-student:1006
    prefer-ip-address: true
  client:
    service-url:
      defaultZone: http://eureka2001.xiaoyang.com:2001/eureka/,http://eureka2002.xiaoyang.com:2002/eureka/,http://eureka2003.xiaoyang.com:2003/eureka/

info:
  groupId: com.xiaoyang.testSpringcloud
  artifactId: microservice-student-provider-hystrix-1006
  version: 1.0-SNAPSHOT
  userName: http://xiaoyang.com
  phone: 123456


啟動類配置

@EnableCircuitBreaker
@EntityScan("com.xiaoyang.*.*")
@EnableEurekaClient
@SpringBootApplication

這樣的話 就有了 hystrix叢集服務
我們新建專案microservice-student-consumer-hystrix-turbine-91
pom.xml加下依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>
spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-turbine</artifactId> </dependency>

application.yml

server:
  port: 91
  context-path: /
eureka:
  client:
    service-url:
      defaultZone: http://eureka2001.xiaoyang.com:2001/eureka/,http://eureka2002.xiaoyang.com:2002/eureka/,http://eureka2003.xiaoyang.com:2003/eureka/
turbine:
  app-config: microservice-student   # \u6307\u5B9A\u8981\u76D1\u63A7\u7684\u5E94\u7528\u540D\u79F0
  clusterNameExpression: "'default'" #\u8868\u793A\u96C6\u7FA4\u7684\u540D\u5B57\u4E3Adefault
spring:
  application:
    name: turbine

Feign、Hystrix整合

前面的程式碼,用@HystrixCommand fallbackMethod是很不好的,因為和業務程式碼耦合度太高,不利於維護,所以需要解耦,這我們講下Feign Hystrix整合
comm專案

package com.xiaoyang.microservicecommon.service;

import com.xiaoyang.microservicecommon.entity.Student;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import java.util.List;
import java.util.Map;

/**
 * Student Feign介面客戶端
 *
 * @author xiaoyang
 */
@FeignClient(value = "MICROSERVICE-STUDENT",fallbackFactory=StudentClientFallbackFactory.class)
public interface StudentClientService {

    /**
     * 根據id查詢學生資訊
     *
     * @param id
     * @return
     */
    @GetMapping(value = "/student/get/{id}")
    public Student get(@PathVariable("id") Integer id);

    /**
     * 查詢學生資訊
     *
     * @return
     */
    @GetMapping(value = "/student/list")
    public List<Student> list();

    /**
     * 新增或者修改學生資訊
     *
     * @param student
     * @return
     */
    @PostMapping(value = "/student/save")
    public boolean save(Student student);

    /**
     * 根據id刪除學生資訊
     *
     * @return
     */
    @GetMapping(value = "/student/delete/{id}")
    public boolean delete(@PathVariable("id") Integer id);

    @RequestMapping("/student/ribbon")
    public String ribbon();

    @RequestMapping("/student/hystrix")
    public Map<String, Object> hystrix();
}

StudentClientFallbackFactory

package com.xiaoyang.microservicecommon.service;

import com.xiaoyang.microservicecommon.entity.Student;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author xiaoyang
 * @create  2020-12-14 19:24
 */
@Component
public class StudentClientFallbackFactory implements FallbackFactory<StudentClientService> {
    @Override
    public StudentClientService create(Throwable cause) {
        return new StudentClientService() {

            @Override
            public boolean save(Student student) {
                return false;
            }

            @Override
            public List<Student> list() {
                return null;
            }

            @Override
            public Map<String, Object> hystrix() {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("code", 500);
                map.put("info", "系統繁忙,稍後重試");
                return map;
            }

            @Override
            public Student get(Integer id) {
                return null;
            }

            @Override
            public boolean delete(Integer id) {
                return false;
            }

            @Override
            public String ribbon() {
                return null;
            }
        };
    }
}

ribbon和hystrix超時時間設定

先看消費端配置

server:
  port: 80
  context-path: /
eureka:
  client:
    service-url:
      defaultZone: http://eureka2001.xiaoyang.com:2001/eureka/,http://eureka2002.xiaoyang.com:2002/eureka/,http://eureka2003.xiaoyang.com:2003/eureka/
    register-with-eureka: false
feign:
  hystrix:
    enabled: true
ribbon:
  ReadTimeout: 550 #請求處理的超時時間
  ConnectTimeout: 550 #請求連線的超時時間
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 600

服務端:hystrix04

@ResponseBody
    @GetMapping(value="/hystrix")
    public Map<String,Object> hystrix() throws InterruptedException{
        Thread.sleep(500);
        return studentService.hystrix();
    }

服務端:hystrix05、hystrix06

/**
     * 測試Hystrix服務降級
     * @return
     * @throws InterruptedException
     */
    @ResponseBody
    @GetMapping(value="/hystrix")
    public Map<String,Object> hystrix() throws InterruptedException{
        Thread.sleep(100);
        return studentService.hystrix();
    }

這裡可以看到ribbon的超時時間設定短於hystrix,但是這裡訪問的時候,controller層分別sleep了0.1s和0.5s,ribbon的超時設定為0.55s。那麼,訪問的時候,是可以正常訪問的,並不會ribbon超時或者熔斷。

問題來了

眾所周知,ribbon是有重試機制的,而且是4次

如果這時候我斷掉hystrix04服務,ribbon的輪詢機制在輪詢訪問hystrix04時,由於它已經斷掉,它的訪問超時時間是0.5s,而hystrix的超時降級熔斷時間為0.6s,此時雖然ribbon超時(或其他原因),但是是第一次訪問,且超時時間小於熔斷超時時間,所以不會觸發熔斷,輪詢機制會切換到其他節點去

但是重新整理一次瀏覽器,第二次輪詢到hystrix04服務提供者時,就會觸發熔斷,因為加上第一次的訪問時間,已經超過了hystrix的熔斷超時設定,那麼這個時候ribbon重試失敗 ,觸發熔斷(非完全熔斷,具體可看上篇博文)
在這裡插入圖片描述

所以,如果不考慮ribbon的重試機制,ribbon和hystrix的超時設定並不一定非要誰大誰小,但是重試機制個人覺得是非常重要的,如果沒有重試機制,節點超時或者因為其他原因斷掉後就不用這個節點,不太現實(一個節點相當於一個伺服器)

而要考慮ribbon的重試機制,建議將hystrix降級熔斷的超時時間設定比ribbon超時時間長,不然重試機制的意義在哪,一重試你就熔斷了,hystrix超時時間設定長點,即使重試時此節點連線不上他也會負債均衡分發到另一個節點,不會進行錯誤資訊展示

具體可以自行測試
over…