SpringCloud 8:Feign

项目搭建参考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,没有异常信息

1000ms

  • micro-order只请求了一次

在这里插入图片描述

  • 没有异常信息,hystrix中断了请求

在这里插入图片描述

代码下载地址

https://gitee.com/fisher3652/springcloud-eureka.git

©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页