Hystrix use

Use Hystrix for fusing

To implement a fuse break, you first need to add it to the request caller POM file

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
Copy the code

Add the @Enablecircuitbreaker annotation on the startup class and some configuration on the method that calls another microservice

@GetMapping("/checkHystrix/{userId}") @HystrixCommand(threadPoolKey = "checkHystrix1", threadPoolProperties = { @HystrixProperty(name = "coreSize",value = "1"), @HystrixProperty(name = "maxQueueSize",value = "20") }, commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value="2000") }) public  Integer checkHystrix(@PathVariable Long userId) { String url = "http://zhao-service-resume/resume/openstate/"+userId; Integer forObject = restTemplate.getForObject(url, Integer.class); return forObject; }Copy the code

Add thread sleep to the called service for 10 seconds. If you access the above services, you can find Hystrix timeout errors on the interface

Service degradation

Add fallbackMethod = “customeFallback” to the configuration

    public  Integer customeFallback(Long userId){
        return -1;
    }
Copy the code

When a service is down and the server is no longer called, the client can now prepare a local fallback callback that returns a default value. By doing so, the service level is reduced, but still usable, rather than simply dying. However, when configuring a service degradation policy, The degraded (bottom) method must have the same method signature (same argument list, same return value) as the degraded method If the parameter will appear different com.net flix. Hystrix. Contrib. Javanica. Exception. FallbackDefinitionException: fallback method wasn ‘t found: CustomeFallback ([class java.lang.long]) will appear if the return value is different. And the wrapper class and primitive type cannot share the Hint: Fallback method ‘public int com.zp.controller.AutoDeliverController.customeFallback(java.lang.Long)’ must return: class java.lang.Integer or its subclass

Warehouse wall mode (Thread pool isolation mode)

If all fuse methods use A Hystrix thread pool (default is 10 threads) without any thread pool setting, then this will cause A problem. This problem is not caused by the fan out link microservice being unavailable, but by our threading mechanism. If method A requests all 10 threads, Method 2 requests are processed without access to B at all because there are no threads available, not because service B is unavailable. So when configuring Hystrix threads, multiple methods should write to multiple thread pools. This will keep threads from interfering with each other

@GetMapping("/checkHystrix/{userId}") @HystrixCommand(threadPoolKey = "checkHystrix1", threadPoolProperties = { @HystrixProperty(name = "coreSize",value = "1"), @HystrixProperty(name = "maxQueueSize",value = "20") }, commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value="2000") }) public  Integer checkHystrix(@PathVariable Long userId) { String url = "http://zhao-service-resume/resume/openstate/"+userId; Integer forObject = restTemplate.getForObject(url, Integer.class); return forObject; } @GetMapping("/checkHystrixFallback/{userId}") @HystrixCommand(threadPoolKey = "checkHystrix2", threadPoolProperties = { @HystrixProperty(name = "coreSize",value = "2"), @HystrixProperty(name = "maxQueueSize",value = "20") }, commandProperties = { @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value="2000") }, fallbackMethod = "customeFallback" )Copy the code

Sending batch requests through Postman, and using the jStack command, you can see that the thread pools of the two methods are isolated

Meaning of other attributes

            commandProperties = {
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value="2000"),
                    @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds",value = "8000"),
                    @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "2"),
                    @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value="50"),
                    @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value="3000")
            }
Copy the code

Metrics. RollingStats. TimeInMilliseconds this attribute is the fusing of statistical time window defined circuitBreaker. RequestVolumeThreshold this attribute statistics within the time window the number of times of failure, Reach the number after open fuse circuitBreaker. ErrorThresholdPercentage window as a percentage of the number of times failure, Achieve this percentage after open fuse circuitBreaker. SleepWindowInMilliseconds fusing long interval long whether started trying to restore later

Brief source code analysis

First of all, we can be found according to the annotation class @ EnableCircuitBreaker SpringFactoryImportSelector class, the class by generics in the spring. The factories file found in the annotations of the generic configuration class

@Override public String[] selectImports(AnnotationMetadata metadata) { if (! isEnabled()) { return new String[0]; } AnnotationAttributes attributes = AnnotationAttributes.fromMap( metadata.getAnnotationAttributes(this.annotationClass.getName(), true)); Assert.notNull(attributes, "No " + getSimpleName() + " attributes found. Is " + metadata.getClassName() + " annotated with @" + getSimpleName() + "?" ); // Find all possible auto configuration classes, filtering duplicates List<String> factories = new ArrayList<>(new LinkedHashSet<>(SpringFactoriesLoader .loadFactoryNames(this.annotationClass, this.beanClassLoader))); if (factories.isEmpty() && ! hasDefaultFactory()) { throw new IllegalStateException("Annotation @" + getSimpleName() + " found, but there are no implementations. Did you forget to include a starter?" ); } if (factories.size() > 1) { // there should only ever be one DiscoveryClient, but there might be more than // one factory log.warn("More than one implementation " + "of @" + getSimpleName() + " (now  relying on @Conditionals to pick one): " + factories); } return factories.toArray(new String[factories.size()]); }Copy the code

You then find the loaded configuration class in Spring.Factories

org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker=\
org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration

Copy the code

A HystrixCommandAspect is configured in the configuration class, where the main functions of the Hystrix implementation are performed

public Object methodsAnnotatedWithHystrixCommand(final ProceedingJoinPoint joinPoint) throws Throwable { Method method =  getMethodFromTarget(joinPoint); Validate.notNull(method, "failed to get method from joinPoint: %s", joinPoint); if (method.isAnnotationPresent(HystrixCommand.class) && method.isAnnotationPresent(HystrixCollapser.class)) { throw new IllegalStateException("method cannot be annotated with HystrixCommand and HystrixCollapser " + "annotations at the same time"); } MetaHolderFactory metaHolderFactory = META_HOLDER_FACTORY_MAP.get(HystrixPointcutType.of(method)); MetaHolder metaHolder = metaHolderFactory.create(joinPoint); HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder); ExecutionType executionType = metaHolder.isCollapserAnnotationPresent() ? metaHolder.getCollapserExecutionType() : metaHolder.getExecutionType(); Object result; try { if (! metaHolder.isObservable()) { result = CommandExecutor.execute(invokable, executionType, metaHolder); } else { result = executeObservable(invokable, executionType, metaHolder); } } catch (HystrixBadRequestException e) { throw e.getCause(); } catch (HystrixRuntimeException e) { throw hystrixRuntimeExceptionToThrowable(metaHolder, e); } return result; }Copy the code

Using synchronous calls goes to executeObservable and eventually HystrixCommand to get the final processing logic

public R execute() { try { return queue().get(); } catch (Exception e) { throw Exceptions.sneakyThrow(decomposeException(e)); }}Copy the code

Final Future delegate = toObservable().toblocking ().toFuture(); The fuse downgrade operation in Hystrix is done in toObservable()

Welcome to search attention to my public number [micro view technology], and summary of classified interview questions github.com/zhendiao/Ja…