一、项目总体介绍(客户端的熔断机制)
1、项目实现功能
当服务端的程序不可用时(服务宕机或者请求超时),为了保障系统的高可用采用熔断机制
2、项目模块介绍(还是采用系列一的代码,分为四个模块,现在将系列一的用户服务客户端(user-service-consumer)进行改造),只改变系列一的
二、项目代码的实现
2.1、通过Hystrix实现方法对指定方法的熔断
2.1.1、代码实现
---------------------在原来的pom.xml加入Hystrix依赖-------------------------------
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
<version>1.4.5.RELEASE</version>
</dependency>
------------------------在启动应用出(Application)添加激活熔断注解----------------------
package com.gpdi;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.web.client.RestTemplate;
@EnableCircuitBreaker
@EnableDiscoveryClient
@SpringBootApplication
public class Application {
@LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
---------在客户端的UserServiceProxy处的需要做熔断的方法添加注解,并且设置对应的处理方法-------
package com.gpdi.service;//package com.gpdi.service;
import com.gpdi.user.entity.User;
import com.gpdi.user.service.UserService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.ribbon.proxy.annotation.Hystrix;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
/**
* @desc:UserServiceProxy 实现
*
*/
@Service
public class UserServiceProxy implements UserService {
private static final String PROVIDER_SERVER_URL_PREFIX =
"http://user-service-provider";
/**
* 通过 REST API 代理到服务器提供者
*/
@Autowired
private RestTemplate restTemplate;
@Override
public void addUser(User user) {
restTemplate.postForObject(
PROVIDER_SERVER_URL_PREFIX + "/user/save", user, User.class);
}
@HystrixCommand(fallbackMethod = "getAllFallBack")
@Override
public List<User> getAllUser() {
return restTemplate.getForObject(
PROVIDER_SERVER_URL_PREFIX + "/user/list", List.class);
}
@ResponseBody
public List<User> getAllFallBack(){
List<User>list=new ArrayList<User>();
User user=new User();
user.setName("session");
user.setId(1L);
list.add(user);
return list;
}
}
2.2、自定义超时熔断机制
2.2.1、功能描述:当我们客户端调用服务端的时间超过了我们的预期值我们可以直接做熔断后的处理
2.2.2、代码演示
package com.gpdi.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
@RestController
public class UserController {
/**
* @desc:对远程服务设置超时自动熔断
*/
@GetMapping(value = "countUserNumber")
public String countUserNumber() {
//创建一个线程池
ExecutorService executorService = Executors.newFixedThreadPool(1);
//模拟调用一个服务端应用程序
Future f = executorService.submit(() -> {
Random random = new Random();
int time = random.nextInt(100);
System.out.println("当前数值是"+time);
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
try {
f.get(50, TimeUnit.MILLISECONDS);
return "请求成功";
} catch (Exception e) {
return "请求超时";
}
}
}