天天看點

SpringCloud:服務保護——Hystrix

一,Hystrix

    SpringCloud體系中,自提供了Hystrix進行服務保護。對用戶端通路進行了服務降級,服務隔離以及服務熔斷等等處理。

二,環境搭建

    Eureka實作基本服務調用環境搭建參考博文:SpringCloud:注冊中心——Eureka,本篇博文在基礎上進行處理

三,添加Maven坐标依賴

<!-- hystrix斷路器 -->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
  </dependencies>
           

四,添加配置資訊

### 開啟hystrix斷路器
feign:
  hystrix:
    enabled: true

### hystrix啟動時間
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds : 1000
           

五,啟動類通過@Enable子產品開啟Hystrix

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
// 啟動Hystrix進行服務保護
@EnableHystrix
public class OrderApp {

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

六,服務端代碼

package com.gupao.member.service.impl;

import com.gupao.api.service.IMemberServier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author pj_zhang
 * @create 2019-01-09 23:48
 **/
@RestController
public class MemberService implements IMemberServier {

    @Value("${server.port}")
    private Integer serverPort;

    @Override
    @RequestMapping("/getMember_1")
    public String getMember_1() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("getMember_1 Thread Name : " + Thread.currentThread().getName());
        return "MemberService.getMember_1, serverPort : " + serverPort;
    }

    @Override
    @RequestMapping("/getMember_2")
    public String getMember_2() {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("getMember_2 Thread Name : " + Thread.currentThread().getName());
        return "MemberService.getMember_2, serverPort : " + serverPort;
    }
}
           

七,服務保護Service實作

    1,服務保護分别通過服務通路和服務調用兩方面對Hystrix服務保護進行示範;差別在于,

        * 服務通路:服務保護從浏覽器發起Http請求開始生效,目前服務代碼也在服務保護範圍内(這部分實作比較粗糙,暫時沒有找到統一處理方式)。這種服務保護機制對目前服務和服務端服務進行了統一保護,但同時也造成了耦合,如果本地業務已經超過Hystrix門檻值,則服務端接口根本不會調用;

        * 服務調用:服務保護從開始調用服務端接口開始生效,目前服務代碼不在服務保護範圍内,這種實作提供了統一的實作的方式;但是這種方式相對來講隻對服務端進行了保護,目前服務依舊可能遭受之前提到的各種服務問題;

        * 隻做示範,不要吐槽同時用,感覺同時用并不太好;向有更好方案的大神求方案!!!

    2,基于服務通路的服務保護

package com.gupao.order.service.impl;

import com.gupao.api.service.IOrderService;
import com.gupao.order.feign.IMemberServiceFeign;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author pj_zhang
 * @create 2019-01-10 0:04
 **/
@RestController
public class OrderService implements IOrderService {

    @Autowired
    private IMemberServiceFeign memberServiceFeign;

    /**
     * 目前方法交由Hystrix進行服務保護
     * @return
     */
    @Override
	@RequestMapping("/orderToMember_1")
	// @HystrixCommand : Hystrix服務保護注解
	// fallbackMethod : 觸發服務保護後, 執行後面指定方法内容
	// orderToMemberFallback : 服務保護觸發後, 指定執行方法
	@HystrixCommand(fallbackMethod = "orderToMemberFallback")
	public String orderToMember_1() throws InterruptedException {
		Thread.sleep(3000);
		// Hystrix自動開啟服務隔離機制, 目前線程為Hystrix對目前服務建立的獨立的線程池中的線程
        // 從下面示範中可以看到目前線程池與orderToMember_2方法的線程池不同
		System.out.println("orderToMember_1 Thread Name : " + Thread.currentThread().getName());
		return memberServiceFeign.getMember_1();
	}

	/**
	 * 服務保護觸發後, 執行該方法
	 */
	@RequestMapping("/orderToMemberFallback")
	public String orderToMemberFallback() {
		System.out.println("orderToMemberFallback Thread Name : " + Thread.currentThread().getName());
		return "Hystrix進行服務保護, 系統錯誤!!!";
	}

	@Override
	@RequestMapping("/orderToMember_2")
	public String orderToMember_2() {
		System.out.println("orderToMember_1 Thread Name : " + Thread.currentThread().getName());
		return memberServiceFeign.getMember_2();
	}
}
           

        * 關注參數

             -- Hystrix逾時時間為1S

SpringCloud:服務保護——Hystrix

            -- 所有服務(包括服務端服務)睡眠時間為3S,則服務必定逾時

SpringCloud:服務保護——Hystrix

        * 服務降級示範

              -- 服務調用傳回結果,從下圖可以看到服務已經被降級處理

SpringCloud:服務保護——Hystrix

        * 服務隔離示範

              -- 服務降級示範線程号如下

SpringCloud:服務保護——Hystrix

              -- 未交由Hystrix進行服務保護的接口線程号如下;可以看到服務交由Hystrix保護後,線程由Hystrix生成的線程池所建立,而未交由Hystrix保護的服務,線程則為Web容器自身的線程池建立

SpringCloud:服務保護——Hystrix

        * 服務熔斷示範

              -- 暫時無法示範,軟體不全,後續補全!!!

    3,基于服務調用的服務保護 —— 基于Feign用戶端調用進行處理

        * Feign用戶端通過聲明一個Feign接口進行服務調用,接口需要注解@FeignClient,其中@FeignClient自定義了fallback屬性,需要指定對應fallback處理類,進行對應服務保護處理,該指定類最好為目前Feign接口的實作類;處理後,所有Feign用戶端處理的接口都受Hystrix服務保護處理

        * Feign接口

// 通過fallback屬性指定觸發服務保護後, 需要執行的類
@FeignClient(name = "app-itmayiedu-member", fallback = OrderServiceFallback.class)
public interface IMemberServiceFeign extends IMemberServier {
}
           

        * fallback類,服務調用觸發Hystrix服務保護後,會對應執行該類中的服務對應方法,進行服務降級處理

package com.gupao.order.fallback;

import com.gupao.order.feign.IMemberServiceFeign;
import org.springframework.stereotype.Component;

/**
 * @author pj_zhang
 * @create 2019-01-22 21:37
 **/
@Component
public class OrderServiceFallback implements IMemberServiceFeign {
    @Override
    public String getMember_1() {
        System.out.println("getMember_1 Fallback Thread Name : " + Thread.currentThread().getName());
        return "Hystrix進行服務保護, 系統錯誤!!!";
    }

    @Override
    public String getMember_2() {
        System.out.println("getMember_2 Fallback Thread Name : " + Thread.currentThread().getName());
        return "Hystrix進行服務保護, 系統錯誤!!!";
    }
}
           

        * 服務降級示範,通過類聲明處理後,orderToMember_2接口就可以觸發Hystrix

            -- 線程睡眠3S,示範這種服務保護方式對目前服務無影響,隻對調用端産生影響

@Override
@RequestMapping("/orderToMember_2")
public String orderToMember_2() throws InterruptedException {
	Thread.sleep(3000);
	System.out.println("orderToMember_1 Thread Name : " + Thread.currentThread().getName());
	return memberServiceFeign.getMember_2();
}
           
SpringCloud:服務保護——Hystrix
SpringCloud:服務保護——Hystrix

        * 服務隔離示範,從上圖可以看到,目前服務線程和fallback線程并不屬于同一個線程池

        * 服務熔斷示範

繼續閱讀