Feign
- 1. Feign简介
- 2. jar包导入
- 3. 开启Feign客户端功能,创建实体类Student
- 4. 创建StudentService接口,完成对MICRO-ORDER服务的接口绑定
- 5. 创建降级类StudentServiceFallbackFactory,实现FallbackFactory接口
- 6. 创建Feign的异常过滤器FeignErrMessageFilter
- 7. 开启熔断器功能
- 8. 服务提供方micro-order,创建实体类Student,引入fastjson
- 9. 创建StudentService接口
- 10. 创建实现类StudentServiceImpl
- 11. 创建StudentController
- 12. 启动服务
- 13. 调用http://localhost:8083/student/saveStudent接口,保存student实体
- 14. 调用http://localhost:8083/student/getStudentById?id=2,查询id为2的student数据
- 15. 调用异常接口http://localhost:8083/student/errorMessage,走降级方法
- 16. 查看hystrix监控页面
- 17. 超时配置
- 18. 服务提供方micro-order,添加一个超时测试接口
- 19. 服务调用方micro-web,添加调用方法
- 20. 调用超时测试接口
- 代码下载地址
项目搭建参考https://blog.csdn.net/qq_40977118/article/details/104738485
1. Feign简介
- Feign是对服务端和客户端通用接口的封装,让代码可以复用做到统一管理,整合了Ribbon和Hystrix,拥有负载均衡和服务容错功能。
2. jar包导入
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
3. 开启Feign客户端功能,创建实体类Student
@EnableFeignClients(clients = {StudentService.class})
package com.spring.fisher.bean;
import lombok.Data;
@Data
public class Student {
public Integer id;
public String name;
}
4. 创建StudentService接口,完成对MICRO-ORDER服务的接口绑定
- 指定降级类fallbackFactory = StudentServiceFallbackFactory.class,能获取具体异常信息,不推荐使用fallback = StudentServiceFallback.class
package com.spring.fisher.service.feign;
import com.spring.fisher.bean.Student;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(name = "MICRO-ORDER", path = "/feign",
/*fallback = StudentServiceFallback.class,*/
fallbackFactory = StudentServiceFallbackFactory.class)
public interface StudentService {
@GetMapping("/student/getStudentById")
String getStudentById(@RequestParam("id") Integer id);
@GetMapping("/student/saveStudent")
String saveStudent(@RequestBody Student student);
@GetMapping("/student/errorMessage")
String errorMessage();
}
5. 创建降级类StudentServiceFallbackFactory,实现FallbackFactory接口
- 调用对应feign客户端方法出现异常了,就会回调到create方法中,最终会回调到对应的客户端方法中
package com.spring.fisher.service.feign;
import com.spring.fisher.bean.Student;
import feign.hystrix.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class StudentServiceFallbackFactory implements FallbackFactory<StudentService> {
@Override
public StudentService create(Throwable throwable) {
if (throwable == null) {
return null;
}
final String msg = throwable.getMessage();
log.info("StudentServiceFallbackFactory:" + msg);
return new StudentService() {
@Override
public String getStudentById(Integer id) {
log.info("exception:getStudentById=" + msg);
return msg;
}
@Override
public String saveStudent(Student student) {
log.info("exception:saveStudent=" + msg);
return msg;
}
@Override
public String errorMessage() {
log.info("exception:errorMessage=" + msg);
return msg;
}
};
}
}
6. 创建Feign的异常过滤器FeignErrMessageFilter
- 这个过滤器是对异常信息的再封装,把feign的异常信息封装成我们系统的通用异常对象;
- 过滤器把异常返回后,feign前面定义的降级方法就会调到create方法。
package com.spring.fisher.service.feign;
import feign.Response;
import feign.Util;
import feign.codec.ErrorDecoder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
@Slf4j
@Configuration
public class FeignErrMessageFilter {
@Bean
public ErrorDecoder errorDecoder() {
return new FeignErrorDecoder();
}
/**
* 当调用服务时,如果服务返回的状态码不是200,就会进入到Feign的ErrorDecoder中
* 只有这种方式才能获取所有的被feign包装过的异常信息
*/
class FeignErrorDecoder implements ErrorDecoder {
@Override
public Exception decode(String s, Response response) {
RuntimeException runtimeException = null;
try {
String result = Util.toString(response.body().asReader());
log.info("FeignErrorDecoder:result="+result);
runtimeException = new RuntimeException(result);
} catch (IOException e) {
e.printStackTrace();
}
return runtimeException;
}
}
}
7. 开启熔断器功能
#feign开启熔断器
feign.hystrix.enabled=true
#是否对请求进行GZIP压缩
feign.compression.request.enabled=true
#指定压缩的请求数据类型
#feign.compression.request.mime-types=text/xml,application/xml,application/json
#超过该大小的请求会被压缩
#feign.compression.request.min-request-size=2048
#是否对响应进行GZIP压缩
feign.compression.response.enabled=true
8. 服务提供方micro-order,创建实体类Student,引入fastjson
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.37</version>
</dependency>
9. 创建StudentService接口
package com.spring.fisher.service.feign;
import com.spring.fisher.bean.Student;
import java.util.HashMap;
import java.util.Map;
public interface StudentService {
Map<Integer, Object> map = new HashMap();
String queryStudentById(Integer id);
String saveStudent(Student student);
String errorMessage();
}
10. 创建实现类StudentServiceImpl
package com.spring.fisher.service.feign;
import com.alibaba.fastjson.JSONObject;
import com.spring.fisher.bean.Student;
import org.springframework.stereotype.Service;
@Service
public class StudentServiceImpl implements StudentService{
@Override
public String queryStudentById(Integer id) {
Object o=map.get(id);
return JSONObject.toJSONString(o);
}
@Override
public String saveStudent(Student student) {
map.put(student.getId(), student);
return "save success!";
}
@Override
public String errorMessage() {
try {
int result = 1 / 0;
return String.valueOf(result);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
}
11. 创建StudentController
package com.spring.fisher.Controller;
import com.spring.fisher.bean.Student;
import com.spring.fisher.service.feign.StudentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
public class StudentController implements StudentService {
@Qualifier("studentServiceImpl")
@Autowired
private StudentService studentService;
@RequestMapping("/feign/student/getStudentById")
@Override
public String queryStudentById(@RequestParam("id") Integer id) {
String student = studentService.queryStudentById(id);
log.info("queryStudentById="+student);
return student;
}
@RequestMapping("/feign/student/saveStudent")
@Override
public String saveStudent(@RequestBody Student student) {
String result = studentService.saveStudent(student);
log.info("saveStudent="+result);
return result;
}
@RequestMapping("/feign/student/errorMessage")
@Override
public String errorMessage() {
return studentService.errorMessage();
}
}
12. 启动服务
13. 调用http://localhost:8083/student/saveStudent接口,保存student实体
14. 调用http://localhost:8083/student/getStudentById?id=2,查询id为2的student数据
15. 调用异常接口http://localhost:8083/student/errorMessage,走降级方法
- 先走过滤器FeignErrMessageFilter,获取异常信息,并封装成RuntimeException对象
- 再走降级方法StudentServiceFallbackFactory,获取异常信息,并打印
16. 查看hystrix监控页面
- 可以看出feign内部是开启了hystrix功能
17. 超时配置
- feign配置的ribbon超时时间3000毫秒,hystrix超时时间5000毫秒
18. 服务提供方micro-order,添加一个超时测试接口
- 通过传入的参数,控制方法执行时间
19. 服务调用方micro-web,添加调用方法
20. 调用超时测试接口
- 2000ms,返回结果正常
- 3000ms
- micro-order调用了2次,因为超时导致了重试,但是又因为hystrix设置了5000ms的超时时间,所以在第2次调用的时候被降级了
关闭重试再次请求
- 3000ms,feign通过ribbon因为请求超时中断请求,得到异常信息
- 只请求了一次,得到了异常信息,
修改hystrix的超时时间1000ms
- 1000ms,没有异常信息
- micro-order只请求了一次
- 没有异常信息,hystrix中断了请求