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/") 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); } }