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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章