简单是来说,在分布式系统中,假如有一个请求需要调用A服务,但A服务出现了问题,则这个请求就会阻塞,那么只要调用服务A的请求都会阻塞,当阻塞的请求越来越多,占用的计算机资源就越来越多。进一步来说,就是一个服务出现问题,可能导致所有的请求都不可用,从而导致整个分布式系统都不可用,这就是“雪崩效应”。
----概念参考简书 https://www.jianshu.com/p/b0cd04817dc6
hystrix会创建新的线程池处理受保护的服务,如果该服务请求量过大,不会影响到其他服务或者tomcat自身线程池的使用。
该隔离技术,是限制某个服务的并发数量,对服务的并发数量设置一个阈值,超过该阈值则服务暂停接受新的请求。
如果某个服务调用较慢或者超时较多,熔断该服务的调用,选择本地服务降级处理,和服务降级一起使用。如果服务恢复正常,再恢复调用。
当服务不可用的时候,为了避免让客户端一直等待,可以直接调用本地方法返回给页面友好的提示信息,可以提高用户体验。
接上篇springcloud2.0之feign客户端调用
pom.xml
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-hystrixartifactId>
dependency>
修改服务,模拟超时
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;
}
}
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);
}
}
请求地址:
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