springcloud2.0之hystrix學習

1、雪崩效應

簡單是來說,在分佈式系統中,假如有一個請求需要調用A服務,但A服務出現了問題,則這個請求就會阻塞,那麼只要調用服務A的請求都會阻塞,當阻塞的請求越來越多,佔用的計算機資源就越來越多。進一步來說,就是一個服務出現問題,可能導致所有的請求都不可用,從而導致整個分佈式系統都不可用,這就是“雪崩效應”。
----概念參考簡書 https://www.jianshu.com/p/b0cd04817dc6

2、hystrix如何解決雪崩效應

2.1 服務隔離

2.1.1 線程池隔離

hystrix會創建新的線程池處理受保護的服務,如果該服務請求量過大,不會影響到其他服務或者tomcat自身線程池的使用。

2.1.2 信號量隔離

該隔離技術,是限制某個服務的併發數量,對服務的併發數量設置一個閾值,超過該閾值則服務暫停接受新的請求。

2.2 服務熔斷

如果某個服務調用較慢或者超時較多,熔斷該服務的調用,選擇本地服務降級處理,和服務降級一起使用。如果服務恢復正常,再恢復調用。

2.3 服務降級

當服務不可用的時候,爲了避免讓客戶端一直等待,可以直接調用本地方法返回給頁面友好的提示信息,可以提高用戶體驗。

3、實踐

3.1 代碼準備

接上篇springcloud2.0之feign客戶端調用

3.2 引入hystrix

3.2.1 springcloud-2.0-feign-parent

pom.xml

<!-- SpringCloud netflix hystrix -->
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

3.2.2 springcloud-2.0-feign-member-service

修改服務,模擬超時
MemberServiceImpl

package com.mine.service.impl;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.mine.service.MemberService;
import com.mine.service.model.MemberModel;

@RestController
public class MemberServiceImpl implements MemberService {
	@Value("${server.port}")
	private String port;

	@RequestMapping("/getMember")
	public MemberModel getMember(@RequestParam("name") String name) {
		System.out.println("i am from " + port);

		try {
			Thread.sleep(1500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		MemberModel memberModel = new MemberModel();
		memberModel.setName(name);
		memberModel.setAge(10);
		return memberModel;
	}

}

3.2.3 springcloud-2.0-feign-order-service

bootstrap.properties

server.port=8010

spring.application.name=nacos-order

spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

spring.cloud.nacos.config.server-addr=127.0.0.1:8848
#spring.cloud.nacos.config.file-extension=yml
#spring.cloud.nacos.config.group=dev-group
spring.cloud.nacos.config.shared-dataids=common.properties

ribbon.ReadTimeout=3000
ribbon.ConnectTimeout=3000

feign.hystrix.enabled=true

hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=1000

ribbon.ReadTimeout、ribbon.ConnectTimeout:feign客戶端調用超時時間
feign.hystrix.enabled:開啓hystrix
hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds=1000爲hystrix默認超時時間,毫秒

添加MemberServiceFeignFallback

package com.mine.service.feign.member.fallback;

import org.springframework.stereotype.Service;

import com.mine.service.feign.member.MemberServiceFeign;
import com.mine.service.model.MemberModel;

@Service
public class MemberServiceFeignFallback implements MemberServiceFeign {

	public MemberModel getMember(String name) {
		System.out.println("getMember:線程池名稱爲" + Thread.currentThread().getName());
		MemberModel memberModel = new MemberModel();
		memberModel.setName("admin");
		memberModel.setAge(100);
		return memberModel;
	}

}

修改MemberServiceFeign

package com.mine.service.feign.member;

import org.springframework.cloud.openfeign.FeignClient;

import com.mine.service.MemberService;
import com.mine.service.feign.member.fallback.MemberServiceFeignFallback;

@FeignClient(value = "nacos-member", fallback = MemberServiceFeignFallback.class)
public interface MemberServiceFeign extends MemberService {

}

修改OrderServiceImpl

package com.mine.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.mine.service.OrderService;
import com.mine.service.feign.member.MemberServiceFeign;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@RestController
public class OrderServiceImpl implements OrderService {
	@Autowired
	private MemberServiceFeign memberServiceFeign;

	@RequestMapping("/gerMemberFromOrder")
	public String gerMemberFromOrder(@RequestParam("name") String name) {
		System.out.println("gerMemberFromOrder:線程池名稱爲" + Thread.currentThread().getName());
		return memberServiceFeign.getMember(name).toString();
	}

	@RequestMapping("/getOrder")
	public String getOrder() {
		System.out.println("getOrder:線程池名稱爲" + Thread.currentThread().getName());

		try {
			Thread.sleep(1500);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		return "我是訂單服務!";
	}

	@RequestMapping("/getOrderByName")
	@HystrixCommand(fallbackMethod = "getOrderByNameFallback")
	public String getOrderByName(@RequestParam("name") String name) {
		System.out.println("getOrderByName:線程池名稱爲" + Thread.currentThread().getName());

		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		return "我是" + name + "訂單服務!";
	}

	private String getOrderByNameFallback(String name) {
		System.out.println("getOrderByNameFallback:線程池名稱爲" + Thread.currentThread().getName());
		return "我是默認訂單!";
	}

}

修改NacosAppOrder

package com.mine;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
@EnableHystrix
public class NacosAppOrder {

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

}

3.3 控制檯日誌

請求地址:

http://localhost:8010/gerMemberFromOrder?name=%E5%BC%A0%E4%B8%89
http://localhost:8010/getOrder
http://localhost:8010/getOrderByName?name=order

控制檯日誌

gerMemberFromOrder:線程池名稱爲http-nio-8010-exec-5
getMember:線程池名稱爲HystrixTimer-2

getOrder:線程池名稱爲http-nio-8010-exec-8

getOrderByName:線程池名稱爲hystrix-OrderServiceImpl-2
java.lang.InterruptedException: sleep interrupted
getOrderByNameFallback:線程池名稱爲HystrixTimer-1
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章