Spring Cloud Alibaba Sentinel supports not only RestTemplate but also Feign. If we want to switch from Hystrix to Sentinel, it is very convenient. Here’s how Feign is supported and how it works.

Integrate Feign use

Spring-cloud-starter-alibaba-sentinel dependencies still need to be added as follows:

<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> < version > 0.2.1. RELEASE < / version > < / dependency >Copy the code

Sentinel support for Feign needs to be enabled in the configuration file:

feign.sentinel.enabled=true
Copy the code

Then we define the Feign Client we need to call:

@FeignClient(name = "user-service", fallback = UserFeignClientFallback.class)
public interface UserFeignClient {
	
	@GetMapping("/user/get")
	public String getUser(@RequestParam("id") Long id);
	
}
Copy the code

Define the fallback class UserFeignClientFallback:

@Component
public class UserFeignClientFallback implements UserFeignClient {

	@Override
	public String getUser(Long id) {
		return "fallback"; }}Copy the code

Test code:

@Autowired
private UserFeignClient userFeignClient;

@GetMapping("/testFeign")
public String testFeign() {
	return userFeignClient.getUser(1L);
}
Copy the code

You can stop the user-service for this Client and see that the output says “fallback”.

If you want to limit the flow of Feign calls, the resource name rules are accurate to the interface, using the interface we defined above, the resource name is GET:http://user-service/user/get, as to how to define the resource name, the following source code analysis you will know.

The principle of analysis

First see how SentinelFeignAutoConfiguration in automatic configuration:

@Bean
@Scope("prototype")
@ConditionalOnMissingBean
@ConditionalOnProperty(name = "feign.sentinel.enabled")
public Feign.Builder feignSentinelBuilder() {
	return SentinelFeign.builder();
}
Copy the code

The feign.sentinel.enabled in @conditionalonProperty is decisive, which is why we need to specify Feign.sentinel. enabled=true in the configuration file.

Here’s the implementation in SentinelFeign.Builder:

Build method to realize the super invocationHandlerFactory method, namely dynamic proxy factory, building InvocationHandler object.

The build will obtain in Feign Client information, such as fallback, fallbackFactory etc., and then create a SentinelInvocationHandler, SentinelInvocationHandler inherited InvocationHandler.

@Override
public Feign build() {
	super.invocationHandlerFactory(new InvocationHandlerFactory() { @Override public InvocationHandler create(Target target, Map<Method, Get Feign MethodHandler > dispatch) {/ / Client Bean Object feignClientFactoryBean = Builder. Enclosing applicationContext .getBean("&"+ target.type().getName()); Class fallBack = (Class) getFieldValue(feignClientFactoryBean,"fallback"); Class fallbackFactory = (Class) getFieldValue(feignClientFactoryBean,"fallbackFactory"); String name = (String) getFieldValue(feignClientFactoryBean,"name"); Object fallbackInstance; FallbackFactory fallbackFactoryInstance; // Check fallback and fallbackFactory propertiesif(void.class ! = fallback) { fallbackInstance = getFromContext(name,"fallback", fallback,
								target.type());
				return new SentinelInvocationHandler(target, dispatch,
								new FallbackFactory.Default(fallbackInstance));
			}
			if(void.class ! = fallbackFactory) { fallbackFactoryInstance = (FallbackFactory) getFromContext(name,"fallbackFactory", fallbackFactory,
								FallbackFactory.class);
				return new SentinelInvocationHandler(target, dispatch,
								fallbackFactoryInstance);
			}
			returnnew SentinelInvocationHandler(target, dispatch); } // omit some code}); super.contract(new SentinelContractHolder(contract));return super.build();
}
Copy the code

SentinelInvocationHandler the invoke method for the processing of current limiting fuse inside.

// GET the resourceName (GET:http://user-service/user/get) String resourceName = methodmetadata.template ().method().touppercase () +":"
					+ hardCodedTarget.url() + methodMetadata.template().url();
Entry entry = null;
try {
	ContextUtil.enter(resourceName);
	entry = SphU.entry(resourceName, EntryType.OUT, 1, args);
	result = methodHandler.invoke(args);
}
catch (Throwable ex) {
	// fallback handle
	if(! BlockException.isBlockException(ex)) { Tracer.trace(ex); }if(fallbackFactory ! Object fallbackResult = fallBackMethodMap.get (method).invoke(fallBackFactory.create (ex), args);return fallbackResult;
		}
		catch (IllegalAccessException e) {
			// shouldn't happen as method is public due to being an interface throw new AssertionError(e); } catch (InvocationTargetException e) { throw new AssertionError(e.getCause()); }} // omit..... }Copy the code

conclusion

In general, the integration of these frameworks has some similarities. The RestTemplate integration is similar to @loadBalanced in the Ribbon. This Feign integration can be referenced from other frameworks, most notably Hystrix.

If Hystrix wants to fuse Feign calls, it must be wrapping HystrixCommand around Feign requests. In the same way, all we have to do to find out how Hystrix is packaged is replace Hystrix code with Sentinel code.

InvocationHandlerFactory is used to create the dynamic proxy factory, there is the default implementation, also have the realization of the Hystrix feign. Hystrix. HystrixFeign.

Feign build(final FallbackFactory<? > nullableFallbackFactory) { super.invocationHandlerFactory(newInvocationHandlerFactory() {
        @Override public InvocationHandler create(Target target,
            Map<Method, MethodHandler> dispatch) {
          returnnew HystrixInvocationHandler(target, dispatch, setterFactory, nullableFallbackFactory); }}); super.contract(new HystrixDelegatingContract(contract));return super.build();
}
Copy the code

Isn’t with Sentinel packaging similar to the code above, the difference is Sentinel structure is SentinelInvocationHandler, Hystrix HystrixInvocationHandle structure. HystrixCommand is wrapped in the Invoke method of HystrixInvocationHandler.

Welcome to join my knowledge planet, exchange technology together, learn free ape world courses (Cxytiandi.com/course)

PS: Currently, we are organizing a team to study Sentinel under the leadership of star owners. Wait for you!