preface
Fegin is a declarative pseudo Http client, which makes it easier to write Http clients. With Feign, you only need to create an interface and annotate it. It has pluggable annotation feature and can use fegin annotation and JAX-RS annotation. Fegin supports pluggable encoders and decoders. Fegin integrates the Ribbon by default, so it can also use load balancing and other features, and because it follows the spring cloudcommon, it can be used with eureka, nacos and other registries.
At present, the degradation fuse of fegin can be realized by Hystrix, sentinel, etc. in this paper, the degradation of fegin is realized by sentinel.
Note: the sentinel used by fegin is basically the same as that used by Hystrx, except that the configuration file can be modified to the following configuration
feign: sentinel: enabled: true
Basic implementation of degradation
We create two services (specific code)
An interface is provided in the User service to get the User object
JcRy: javabean of user object
controller:
@GetMapping("/user/test") public Object test(String id, HttpServletRequest request) { JcRy jcRy = jcRyService.getById(id); return jcRy; }
service:
public JcRy getById(String id) { JcRy jcRy = jcRyDAO.selectById(id); return jcRy; }
Data service uses fegin to call
feginService:
@FeignClient( value = "service-user", fallbackFactory = UserServiceFallbackFactory.class ) public interface UserService { @GetMapping("/user/test") Object test(@RequestParam String id); }
Degradation of fegin:
@Component public class UserServiceFallbackFactory implements FallbackFactory<UserService> { @Override public UserService create(Throwable throwable) { throwable.printStackTrace(); System.out.println("Downgrade"); return id -> new JcRy(); } }
We did not perform degradation after calling the test method in feginService
Here we modify the service of the User project to add a thread sleep
@Override public Object getById(String id) { //Adding thread sleep causes Data server to call fegin to report timeout error try{TimeUnit.MINUTES.sleep(1);}catch (Exception e){} JcRy jcRy = jcRyDAO.selectById(id); return jcRy; }
The default timeout of a fegin request is 1 second. We can directly set it to 1 minute, and a timeout error will be reported here to enter the degradation
Through the above example, we know that when there is an error within the service called by fegin and the data cannot be returned, fegin will enter the degradation method. But if there is no exception within the service called by fegin and the data is returned normally, will fegin enter the degradation?
Let's take a look at other ways to get into relegation
Modify the controller in the User service: we only return one map this time
@GetMapping("/test") public Object test(String id, HttpServletRequest request) { // JcRy jcRy = jcRyService.getById(id); Map<String,Integer> map=new HashMap<>(); map.put("status",400); return map; }
Continue to call feginService:
Not only is fegin degraded, but there is no error reported on the console. You should know that there is such a code in our downgrade that can print error reported: throwable.printStackTrace();
When we trace the source code, we will find that the system executes on the adapter of CoyoteAdapter, which judges the return value of fegin. If there is a status of 400, it will be degraded. That's why it's going to be relegated when you return properly.
It is also defined in the adapter that the status is 500 and the return value is degraded, which shows that the design and encapsulation of fegin is really perfect..
I found this problem when I called spring security's authentication request through fegin when doing gateway authentication, so I should pay attention to this feature when designing the request in the future, and don't degrade the system when it's not clear.
Love old fellow iron, give a complimentary complimentary point, Thanks.