一:Feign集成Hystrix实现声明式服务调用:定义FeignClient接口。指定服务提供者、指定回调
/**
* : 描述信息
*
* @author liyy
* @date 2018-07-28 14:59
*/
@FeignClient(value = "microservice-provider-user",fallback = UserFeignFallBack.class)
public interface UserFeignClient{
@GetMapping(value = "/{id}")
public User findOne(@RequestParam("id") Long id);
}
二:定义降级类实现上述接口,定义回调函数
/**
* : 描述信息
*
* @author liyy
* @date 2018-07-31 11:21
*/
@Component
public class UserFeignFallBack implements UserFeignClient{
public static Logger logger = LoggerFactory.getLogger(UserFeignFallBack.class);
public User findOne(Long id) {
logger.info("断路器打开,执行回调");
User user = new User();
user.setId(id);
user.setAge("-1");
user.setUsername("zs");
return user;
}
}
三:定义客户端。通过feign调用服务。这里有个问题:就是红色标注的代码获取不到breaker(一直返回null,所以无法打印断路器的状态,解决不掉不过不影响测试)
/**
* : 描述信息
*
* @author liyy
* @date 2018-07-28 15:13
*/
@RestController
public class FeignController {
public static Logger logger = LoggerFactory.getLogger(FeignController.class);
@Autowired
private UserFeignClient feignClient;
@GetMapping(value="/feign/{id}")
public User findOne(@PathVariable Long id){
System.out.println("id:"+id);
User u = feignClient.findOne(id);
HystrixCircuitBreaker breaker = HystrixCircuitBreaker.Factory.getInstance(HystrixCommandKey.Factory.asKey("UserFeignClient#findOne()"));
logger.info("断路器的状态:{}",breaker);
return u;
}
}
四:配置文件
bootstrap.yml
#添加feign对hystrix的支持.默认是false
feign:
hystrix:
enabled: true
#修改feign客户端的超时时间 500ms
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 2000 #客户端超时时间2000ms
circuitBreaker:
requestVolumeThreshold: 3 #请求并发数
application.yml
server:
port: 8020
spring:
application:
name: microservice-consumer-movie-feign
eureka:
client:
service-url:
defaultZone: http://discovery:8761/eureka/
instance:
prefer-ip-address: true
@GetMapping("/{id}")
@ResponseBody
public User findById(@PathVariable Long id) throws InterruptedException {
User user = userRepository.findOne(id);
Thread.sleep(1000);//延迟1000ms相应
return user;
}
timeoutInMilliseconds: 2000 #客户端超时时间2000ms
Thread.sleep(1000);//延迟800ms相应
Hystrix默认超时时间为1000ms。
当Thread.sleep(1000);//延迟1000ms。设置超过2000ms.就会触发超时调用fallback函数返回
{"id":1,"username":"zs","age":"-1"}
否则就可以正常调用返回正常结果{"id":1,"username":"tom","age":"12"}
编写JUNIT测试代码:模拟一个mvc请求
package com.itmuch.cloud.microserviceconsumermoviefeign; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.web.context.WebApplicationContext; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureMockMvc public class MicroserviceConsumerMovieFeignApplicationTests { @Autowired private MockMvc mockMvc; /*@Before public void init(){ mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); //初始化MockMvc对象 }*/ @Test public void test(){ String responseString = null; //将相应的数据转换为字符串 try { responseString = mockMvc.perform( get("/feign/1") .contentType(MediaType.APPLICATION_FORM_URLENCODED) ).andExpect(status().isOk()) //返回的状态是200 .andDo(print()) //打印出请求和相应的内容 .andReturn().getResponse().getContentAsString(); } catch (Exception e) { e.printStackTrace(); } System.out.println("--------返回的json = " + responseString); } }