天天看點

hystrix服務雪崩解決方法

在上一篇文章中已經說明了服務雪崩是什麼,然後還列出了服務雪崩的幾種解決方法,包括:降級服務、請求緩存、請求合并、服務熔斷這4種方法。

上一篇服務雪崩

然後這一篇列出其他的幾種方法。

線程池隔離

不使用線程池隔離會互相影響,使用線程池隔離互不影響。

pom中加入:

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
			<groupId>com.netflix.hystrix</groupId>
			<artifactId>hystrix-javanica</artifactId>
			<version>RELEASE</version>
</dependency>
           

配置檔案中不需要添加什麼。

目錄結構:

hystrix服務雪崩解決方法

ProductController代碼:

@RestController
public class ProductController {
	@Autowired
	private ProductService productService;
	@RequestMapping(value="list",method=RequestMethod.GET)
	public List<Product> listProduct(){
		List<Product> list= this.productService.listProduct();
		return list;
	}
}
           

ProductService代碼:

@Service
public class ProductService {
	@Autowired
	private LoadBalancerClient loadBalancerClient;	//ribbon	負載均衡用戶端
	@HystrixCommand(groupKey="e-book-product", commandKey = "listProduct",
		    threadPoolKey="e-book-product", 
		    		threadPoolProperties = {
		            @HystrixProperty(name = "coreSize", value = "30"),//線程池大小
		            @HystrixProperty(name = "maxQueueSize", value = "100"),//最大隊列長度
		            @HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),//線程存活時間
		            @HystrixProperty(name = "queueSizeRejectionThreshold", value = "15")//拒絕請求
		    },
		    fallbackMethod = "fallback")
	public List<Product> listProduct(){
		//擷取eurekaone-provider用戶端
		ServiceInstance	si=loadBalancerClient.choose("e-book-product");
		StringBuffer sb = new StringBuffer("");
		sb.append("http://");
		//擷取ip位址
		sb.append(si.getHost());
		sb.append(":");
		//擷取端口号
		sb.append(si.getPort());
		sb.append("/product/list");
		System.out.println(sb.toString());  
		RestTemplate rt = new RestTemplate();
		//對象為Product集合
		ParameterizedTypeReference<List<Product>> typeRef =new ParameterizedTypeReference<List<Product>>(){};
		//參數是浏覽器位址,請求方法,和轉化為的對象
		ResponseEntity<List<Product>> resp= rt.exchange(sb.toString(),HttpMethod.GET, null, typeRef);
		List<Product> plist = resp.getBody();
		return plist;
	}
	public List<Product> fallback() {
		List<Product> list = new ArrayList<Product>();
		list.add(new Product(-1,"fallback"));
		return list;
	}
}
           

測試結果:

hystrix服務雪崩解決方法

注解解釋:

groupKey=“e-book-product”, commandKey = “listProduct”,threadPoolKey=“e-book-product”,每一個線程池對應一個product,commandKey 是接口名,

threadPoolKey是product名稱。

信号量隔離

當請求量過大的時候就會進入fallback中。

pom檔案中加入:

<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
			<groupId>com.netflix.hystrix</groupId>
			<artifactId>hystrix-javanica</artifactId>
			<version>RELEASE</version>
</dependency>
           

配置檔案中不需要加入什麼。

ProductController代碼:

@RestController
public class ProductController {
	@Autowired
	private ProductService productService;
	@RequestMapping(value="list",method=RequestMethod.GET)
	public List<Product> listProduct(){
		List<Product> list= this.productService.listProduct();
		return list;
	}
}
           

ProductService代碼:

@Service
public class ProductService {
	@Autowired
	private LoadBalancerClient loadBalancerClient;	//ribbon	負載均衡用戶端
	@HystrixCommand(fallbackMethod = "fallback",
			commandProperties = {     @HystrixProperty(name=HystrixPropertiesManager.EXECUTION_ISOLATION_STRATEGY, value="SEMAPHORE"),// 信号量 隔離
		      @HystrixProperty(name=HystrixPropertiesManager.EXECUTION_ISOLATION_SEMAPHORE_MAX_CONCURRENT_REQUESTS, value="100")//信号量最大并發度
		    })
	public List<Product> listProduct(){
		//擷取eurekaone-provider用戶端
		ServiceInstance	si=loadBalancerClient.choose("e-book-product");
		StringBuffer sb = new StringBuffer("");
		sb.append("http://");
		//擷取ip位址
		sb.append(si.getHost());
		sb.append(":");
		//擷取端口号
		sb.append(si.getPort());
		sb.append("/product/list");
		System.out.println(sb.toString());  
		RestTemplate rt = new RestTemplate();
		//對象為Product集合
		ParameterizedTypeReference<List<Product>> typeRef =new ParameterizedTypeReference<List<Product>>(){};
		//參數是浏覽器位址,請求方法,和轉化為的對象
		ResponseEntity<List<Product>> resp= rt.exchange(sb.toString(),HttpMethod.GET, null, typeRef);
		List<Product> plist = resp.getBody();
		return plist;
	}
	public List<Product> fallback() {
		List<Product> list = new ArrayList<Product>();
		list.add(new Product(-1,"fallback"));
		return list;
	}
}
           

與線程池隔離隻是改變了一下注解。注解注意的地方是最大信号量和value的值。

測試結果:

hystrix服務雪崩解決方法

線程池隔離和信号量隔離差別,使用場景

hystrix服務雪崩解決方法

Feign服務降級

pom中加入:

<dependency>
			<groupId>${project.parent.groupId}</groupId>
			<artifactId>e-book-product-api</artifactId>
			<version>${project.parent.version}</version>
</dependency>
<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
           

配置檔案加入:

#Feign預設是不開啟Hystrix
feign.hystrix.enabled=true
           

目錄結構:

hystrix服務雪崩解決方法

ProductController代碼:

@RestController
public class ProductController {
	@Autowired
	private ProductService productService;
	@RequestMapping(value="list",method=RequestMethod.GET)
	public List<Product> listProduct(){
		List<Product> list= this.productService.listProduct();
		return list;
	}
}
           

ProductService代碼:

@FeignClient(name="e-book-product",fallback=ProductServiceFallback.class)
public interface ProductService {
	//無參
	@RequestMapping(value="product/list",method=RequestMethod.GET)
	public List<Product> listProduct();
	
}
           

ProductServiceFallback代碼:

@Component
public class ProductServiceFallback implements ProductService{
	@Override
	public List<Product> listProduct() {
		List<Product> list = new ArrayList<Product>();
		list.add(new Product(-1,"fallback"));
		return list;
	}
}
           

測試結果:

當consumer和product都啟動的時候:

hystrix服務雪崩解決方法

當關閉product的時候:

hystrix服務雪崩解決方法

就會進入fallback方法裡面。

Feign服務降級後的異常記錄

上面的例子是Feign服務降級,然後我們可以把服務降級的異常記錄下來。

這個的pom檔案和配置檔案與上面是一樣的。

目錄結構:

hystrix服務雪崩解決方法

ProductController代碼

@RestController
public class ProductController {
	@Autowired
	private ProductService productService;
	@RequestMapping(value="list",method=RequestMethod.GET)
	public List<Product> listProduct(){
		List<Product> list= this.productService.listProduct();
		return list;
	}
}
           

ProductService代碼:

@FeignClient(name="e-book-product",fallbackFactory=ProductServiceFallbackFactory.class)
public interface ProductService {
	//無參
	@RequestMapping(value="product/list",method=RequestMethod.GET)
	public List<Product> listProduct();
}
           

ProductServiceFallbackFactory代碼:

@Component
public class ProductServiceFallbackFactory implements FallbackFactory<ProductService>{
	private Logger logger = LoggerFactory.getLogger(ProductServiceFallbackFactory.class);
	@Override
	public ProductService create(final Throwable arg0) {
		return new ProductService() {
			@Override
			public List<Product> listProduct() {
				logger.warn("fallback exception:",arg0);
				List<Product> list = new ArrayList<Product>();
				list.add(new Product(-1,"fallback"));
				return list;
			}
		};
	}
}
           

這裡主要繼承的接口變為了FallbackFactory

然後加入了private Logger logger = LoggerFactory.getLogger(ProductServiceFallbackFactory.class);

和logger.warn(“fallback exception:”,arg0);

啟動consumer和product測試:

hystrix服務雪崩解決方法

當關閉product時:

hystrix服務雪崩解決方法
hystrix服務雪崩解決方法

就會列印出異常日志。

繼續閱讀