[SpringCloud] 12 Hystrix Fuse

1. What is Hystrix and why do I need him?

1. In the micro-service architecture, services are split into individual services based on business, and there is a dependency between services (e.g. user adjusts commodities,
Adjust inventory, order, etc.), using RestTemplate+Ribbon and Feign between multiple microservices in Spring Cloud
To call.

2. Problems with Distributed Micro-Service Architecture

a: Services are not guaranteed to be 100% available on links invoked between services for network, resource busy, or their own reasons.

b: If there is a problem with a single service, the call to this service will be blocked by a thread, resulting in a long response time or unavailability. In this case, if there are a large number of requests flowing in, the container's thread resources will be exhausted and the service will be paralyzed.

c: Dependencies between services, failures can spread and have catastrophic consequences for the entire micro-service system, which is the "avalanche" effect of service failures.

3. What is service meltdown

A: The fuse mechanism is a micro-service link protection mechanism against avalanche effect.In a microservice architecture, it is common for a request to call multiple services.Chain failures occur when a microservice on the link invoked between services is unavailable or the response time is too long.

b: When a failed call reaches a certain threshold (default is 20 calls failing in 5 seconds), the fuse mechanism starts.In the SpringCloud framework, the fuse mechanism is implemented through Hystrix, which monitors the status of calls between microservices.

c: The comment for the fuse mechanism is @HystrixCommand

4. What to do after an exception occurs?

a: Use the @HystrixCommand annotation
b: When a call to a service method fails and an error message is thrown, the fallbackMethod in the @HystrixCommand comment is automatically called
Method in the current class specified by the property

2. Code implementation

1,appliction.yml

server:
  port: 8001

mybatis:
  config-location: classpath:mybatis/mybatis.cfg.xml
  type-aliases-package: com.haoxiansheng.springcloud.entities # Package in which all Entity alias classes are located
  mapper-locations: classpath:mybatis/mapper/*.xml   #mybatis/mapper/**/*.xml

spring:
  application:
    name: microservice-product #This is important, and it is generally based on this name that subsequent calls between services and services will be made
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/market?useSSL=false&autoReconnect=true&useUnicode=true&characterEncoding=UTF8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true
    username: root
    password: Gyh@52020
    dbcp2:
      min-idle: 5  # Minimum number of maintained connections in the database connection pool
      initial-size: 5  # Number of Initial Connections
      max-total: 5 # maximum connection
      max-wait-millis: 150  # Maximum timeout waiting for connection acquisition

eureka:
  client:
    registerWithEureka: true #Service Book switch
    fetchRegistry: true # Service Discovery Switch
    serviceUrl:
      defaultZone:  http://127.0.0.1:6002/eureka/, http://127.0.0.1:6001/eureka/
      # Client(Service Provider)Which one to register to Eureka Server Service registry, multiple separated by commas
    instance:
      instanceId: ${spring.application.name}:${server.port}-hystrix # Specify Instance ID,Host name will not be displayed
      preferIpAddress: true #Access paths can display IP addresses

# Adding exposed endpoints to monitored services
management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream


2,mybatis.cfg.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <settings>
        <!--Turn on hump naming-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>
</configuration>

3,ProductMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.zenlayer.springcloud.mapper.ProductMapper">

    <select id="findById" resultType="Product" parameterType="Integer">
   select id, product_name, db_source from product where id=#{id};
  </select>

    <select id="findAll" resultType="Product">
   select id, product_name, db_source from product;
  </select>

    <insert id="addProduct" parameterType="Product">
   INSERT INTO product(product_name, db_source) VALUES(#{productName}, DATABASE());
  </insert>

</mapper>

4,ProductMapper

package com.haoxiansheng.springcloud.mapper;

import com.zenlayer.springcloud.entities.Product;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface ProductMapper {

    Product findById(Integer id);

    List<Product> findAll();

    boolean addProduct(Product product);
}

5,Service

package com.haoxiansheng.springcloud.service;

import com.zenlayer.springcloud.entities.Product;

import java.util.List;

public interface ProductService {

    boolean add(Product product);

    Product get(Integer id);

    List<Product> list();
}


package com.haoxiansheng.springcloud.service.impl;

import com.haoxiansheng.springcloud.mapper.ProductMapper;
import com.haoxiansheng.springcloud.service.ProductService;
import com.zenlayer.springcloud.entities.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class ProductServiceImpl implements ProductService {

    @Autowired
    private ProductMapper productMapper ;

    @Override
    public boolean add(Product product) {
        return productMapper.addProduct(product);
    }

    @Override
    public Product get(Integer id) {
        return productMapper.findById(id);
    }

    @Override
    public List<Product> list() {
        return productMapper.findAll();
    }
}

6,Controller

package com.haoxiansheng.springcloud.controller;

import com.haoxiansheng.springcloud.service.ProductService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.zenlayer.springcloud.entities.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("product")
public class ProductController {

    @Autowired
    private ProductService productService;

    //When an exception occurs to the get method, the hystrixGet method is called to handle it
    @HystrixCommand(fallbackMethod = "getFallback")
    @GetMapping(value = "/get/{id}")
    public Product get(@PathVariable("id") Integer id) {
        Product product = productService.get(id);
        //Analogue exception
        if(product == null) {
            throw new RuntimeException("ID=" + id + "invalid");
        }
        return product;
    }

    //This method is called when the get method has an exception. Note the return value of this method and the parameter list is consistent with the original method
    public Product getFallback(@PathVariable("id") Integer id){

        return new Product(id, "ID" + id +"invalid--@HystrixCommand", "Invalid database");
    }
}

package com.haoxiansheng.springcloud;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;

@EnableHystrix
@EnableEurekaClient
@SpringBootApplication
@MapperScan("com.zenlayer.springcloud.mapper")
public class ProductProvider_8001_Hystrix {
    public static void main(String[] args) {
        SpringApplication.run(ProductProvider_8001_Hystrix.class, args);
    }
}

Tags: Mybatis xml Spring Database

Posted on Thu, 11 Jun 2020 21:46:36 -0400 by shainh