1.Spring Cloud learning
- Feign declarative service invocation
- Hystrix fuse
- Gateway gateway
2.Feign
2.1 feign general
• Feign is a declarative REST client, which uses interface based annotation to facilitate client configuration.
• Feign was originally provided by Netflix, but does not support spring MVC annotation. Later, it was encapsulated by spring cloud and supports spring MVC annotation
Solution, making it easier for users to accept
2.2-Feign-quick start
- Introduce open feign dependency on the consumer side
<!--feign--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency>
- Write Feign call interface
package com.itheima.consumer.feign; import com.itheima.consumer.config.FeignLogConfig; import com.itheima.consumer.domain.Goods; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; /** * * feign Declarative interface. To initiate a remote call. * String url = "http://FEIGN-PROVIDER/goods/findOne/"+id; Goods goods = restTemplate.getForObject(url, Goods.class); * * 1. Define interface * 2. Add the annotation @ FeignClient on the interface and set the value attribute to the application name of the service provider * 3. Write the calling interface, and the declaration rules of the interface shall be consistent with the provider interface. * 4. Inject the interface object and call the interface method to complete the remote call */ @FeignClient(value = "FEIGN-PROVIDER") public interface GoodsFeignClient { @GetMapping("/goods/findOne/{id}") public Goods findGoodsById(@PathVariable("id") int id); }
OrderController
package com.itheima.consumer.controller; import com.itheima.consumer.domain.Goods; import com.itheima.consumer.feign.GoodsFeignClient; 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; import org.springframework.web.client.RestTemplate; @RestController @RequestMapping("/order") public class OrderController { @Autowired private RestTemplate restTemplate; @Autowired private GoodsFeignClient goodsFeignClient; @GetMapping("/goods/{id}") public Goods findGoodsById(@PathVariable("id") int id){ /* String url = "http://FEIGN-PROVIDER/goods/findOne/"+id; // 3. Call method Goods goods = restTemplate.getForObject(url, Goods.class); return goods;*/ Goods goods = goodsFeignClient.findGoodsById(id); return goods; } }
goodsFeignClient reports red, which does not affect the use
- Add the @ EnableFeignClients annotation in the startup class to enable the Feign function
package com.itheima.consumer; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; import org.springframework.cloud.openfeign.EnableFeignClients; @EnableDiscoveryClient // Activate DiscoveryClient @EnableEurekaClient @SpringBootApplication @EnableFeignClients //Enable Feign's function public class ConsumerApp { public static void main(String[] args) { SpringApplication.run(ConsumerApp.class,args); } }
- Test call
2.3 feign timeout configuration
• Feign bottom layer relies on Ribbon to realize load balancing and remote call.
• Ribbon defaults to 1 second timeout.
• timeout configuration:
feign-consumer application.yml
# Set the timeout for the Ribbon ribbon: ConnectTimeout: 1000 # The default connection timeout is 1s. The default unit is milliseconds ReadTimeout: 3000 # The timeout of logical processing is 1s by default, and the default unit is milliseconds
2.4 feign logging
• Feign can only record debug level log information.
feign-consumer application.yml
# Set the current log level to debug. feign only supports logging at the debug level logging: level: com.itheima: debug
• define Feign log level Bean
FeignLogConfig
package com.itheima.consumer.config; import feign.Logger; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class FeignLogConfig { /* NONE,No record BASIC,Record the basic request line and response status code data HEADERS,Record the basic request line, response status code data, and record the response header information FULL;Record the completed request response data */ @Bean public Logger.Level level(){ return Logger.Level.FULL; } }
• enable the Bean:
package com.itheima.consumer.feign; import com.itheima.consumer.config.FeignLogConfig; import com.itheima.consumer.domain.Goods; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; /** * * feign Declarative interface. To initiate a remote call. * String url = "http://FEIGN-PROVIDER/goods/findOne/"+id; Goods goods = restTemplate.getForObject(url, Goods.class); * * 1. Interface definition * 2. Add the annotation @ FeignClient on the interface and set the value attribute to the application name of the service provider * 3. Write the calling interface, and the declaration rules of the interface shall be consistent with the provider interface. * 4. Inject the interface object and call the interface method to complete the remote call */ @FeignClient(value = "FEIGN-PROVIDER",configuration = FeignLogConfig.class) public interface GoodsFeignClient { @GetMapping("/goods/findOne/{id}") public Goods findGoodsById(@PathVariable("id") int id); }
3.Hystrix
3.1-Hystrix - General
• Hystix is an open-source delay and fault-tolerant Library of Netflix, which is used to isolate access to remote services and third-party libraries and prevent cascading failures (avalanches).
• avalanche: when a service fails, the service of the whole link fails
Main functions of Hystix
• isolation
Thread pool isolation
Semaphore isolation
• degradation: abnormal, timeout
• fusing
• current limiting
3.2-Hystrix-downgrade
3.2.1 - provider degradation
Hystix degradation: when the service has an exception or the call times out, the default data is returned
Service provider downgrade
-
In the service provider, introduce hystrix dependency
<!-- hystrix --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
-
Define degradation method
/** * Define the degradation method: * 1. The return value of the method needs to be the same as the original method * 2. The parameters of the method need to be the same as the original method */ public Goods findOne_fallback(int id){ Goods goods = new Goods(); goods.setTitle("Demoted~~~"); return goods; }
- Use the @ HystrixCommand annotation to configure the degradation method
/** * Downgrade: * 1. An exception occurred * 2. Service call timeout * * Default 1s timeout * * @HystrixCommand(fallbackMethod = "findOne_fallback") * fallbackMethod: Specifies the name of the method that is called after downgrading. */ @GetMapping("/findOne/{id}") @HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = { //Set the timeout time of Hystrix, which is 1s by default @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000") }) public Goods findOne(@PathVariable("id") int id){ //1. Make an exception int i = 3/0; try { //2. Sleep for 2 seconds Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } Goods goods = goodsService.findOne(id); goods.setTitle(goods.getTitle() + ":" + port);//Set the port number to the product title return goods; }
- Start the Hystrix function on the startup class: @ enablercircuitbreaker
package com.itheima.provider; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; /** * Startup class */ @EnableEurekaClient //This annotation can be omitted in the new version @SpringBootApplication @EnableCircuitBreaker // Turn on the Hystrix function public class ProviderApp { public static void main(String[] args) { SpringApplication.run(ProviderApp.class,args); } }
3.2.2 - consumer demotion
-
feign component has integrated the hystrix component.
-
Define feign call interface implementation class and copy method, that is, degradation method
GoodsFeignClientFallback
package com.itheima.consumer.feign; import com.itheima.consumer.domain.Goods; import org.springframework.stereotype.Component; /** * Feign Degradation processing class of client * 1. Define a class to implement Feign client interface * 2. Use the @ Component annotation to add the Bean of this class to the SpringIOC container */ @Component public class GoodsFeignClientFallback implements GoodsFeignClient { @Override public Goods findGoodsById(int id) { Goods goods = new Goods(); goods.setTitle("Demoted again~~~"); return goods; } }
-
Use the fallback attribute in the @ FeignClient annotation to set the degradation processing class.
GoodsFeignClient
package com.itheima.consumer.feign; import com.itheima.consumer.domain.Goods; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(value = "HYSTRIX-PROVIDER",fallback = GoodsFeignClientFallback.class) public interface GoodsFeignClient { @GetMapping("/goods/findOne/{id}") public Goods findGoodsById(@PathVariable("id") int id); }
-
Configure and enable feign hystrix. enabled = true
application.yml
# Enable feign's support for hystrix feign: hystrix: enabled: true
3.3-Hystrix fuse
3.3.1 - fusing - concept
• Hystrix fuse mechanism is used to monitor the microservice call. When the failure reaches the predetermined threshold (20 failures in 5 seconds), it will be turned on
Circuit breaker, reject all requests until service returns to normal.
The circuit breaker has three states: open, half open, closed
3.3.2 - fusing - code demonstration
Modify the service provider's method and demonstrate the circuit breaker mechanism
Fuse configuration
• circuitBreaker.sleepWindowInMilliseconds: monitoring time
• circuitBreaker. Requestvolumthreshold: number of failures
• circuitBreaker.errorThresholdPercentage: failure rate
GoodsController
package com.itheima.provider.controller; import com.itheima.provider.domain.Goods; import com.itheima.provider.service.GoodsService; import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; 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; import java.util.Date; /** * Goods Controller service provider */ @RestController @RequestMapping("/goods") public class GoodsController { @Autowired private GoodsService goodsService; @Value("${server.port}") private int port; /** * Downgrade: * 1. An exception occurred * 2. Service call timeout * * Default 1s timeout * * @HystrixCommand(fallbackMethod = "findOne_fallback") * fallbackMethod: Specifies the name of the method that is called after downgrading. */ @GetMapping("/findOne/{id}") @HystrixCommand(fallbackMethod = "findOne_fallback",commandProperties = { //Set the timeout time of Hystrix, which is 1s by default @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value = "3000"), //The monitoring time is 5000 milliseconds by default @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value = "5000"), //Number of failures. Default 20 times @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value = "20"), //The default failure rate is 50% @HystrixProperty(name="circuitBreaker.errorThresholdPercentage",value = "50") }) public Goods findOne(@PathVariable("id") int id){ //If id == 1, an exception occurs= 1 normal access if(id == 1){ //1. Make an exception int i = 3/0; } /*try { //2. Sleep for 2 seconds Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }*/ Goods goods = goodsService.findOne(id); goods.setTitle(goods.getTitle() + ":" + port);//Set the port number to the product title return goods; } /** * Define the degradation method: * 1. The return value of the method needs to be the same as the original method * 2. The parameters of the method need to be the same as the original method */ public Goods findOne_fallback(int id){ Goods goods = new Goods(); goods.setTitle("Demoted~~~"); return goods; } }
3.3.3 - fuse monitoring
• Hystrix provides the function of Hystrix dashboard, which is used to monitor the running status of microservices in real time.
• however, the hystrix dashboard can only monitor one microservice.
• Netflix also provides Turbine for aggregation monitoring.
For fuse monitoring installation, please check the Turbine construction steps md
4.Gateway
4.1 gateway overview
-
Gateway aims to provide a simple and effective unified API routing management method for microservice architecture.
-
In the microservice architecture, different microservices can have different network addresses. Each microservice completes a user request by calling each other. The client may complete a user request by calling the interfaces of N microservices.
-
Existing problems:
1.The client requests different microservices many times, which increases the complexity of the client 2.Authentication is complex, and every service needs to be authenticated 3.http The number of requests for different services increases, and the performance is not high
-
Gateway is the entrance of the system. It encapsulates the internal structure of the application and provides unified services for the client. Some public logic independent of the business function can be realized here, such as authentication, authentication, monitoring, caching, load balancing, traffic control, routing forwarding, etc
-
Among the current gateway solutions, there are Nginx+ Lua, Netflix Zuul, Spring Cloud Gateway and so on
4.2-Gateway-quick start
-
Build gateway module
Create API gateway server module
-
Introduction dependency: Starter gateway
<dependencies> <!--introduce gateway gateway--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!-- eureka-client --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies>
-
Write startup class
package com.itheima.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class ApiGatewayApp { public static void main(String[] args) { SpringApplication.run(ApiGatewayApp.class,args); } }
-
Write configuration file
application.yml
server: port: 80 spring: application: name: api-gateway-server cloud: # Gateway configuration gateway: # Routing configuration: forwarding rules routes: #Gather. # id: unique identification. The default is a UUID # uri: forwarding path # Predictions: conditions used to request matching rules for gateway paths - id: gateway-provider uri: http://localhost:8001/ predicates: - Path=/goods/**
-
Start test
4.3-Gateway-static routing
application. Static routing is written in uri
server: port: 80 spring: application: name: api-gateway-server cloud: # Gateway configuration gateway: # Routing configuration: forwarding rules routes: #Gather. # id: unique identification. The default is a UUID # uri: forwarding path # Predictions: conditions used to request matching rules for gateway paths # Filters: to configure local filters - id: gateway-provider # Static routing uri: http://localhost:8001/ predicates: - Path=/goods/**
4.4-Gateway-dynamic routing
Add @ EnableEurekaClient to the startup class (the new version can be added without)
package com.itheima.gateway; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication @EnableEurekaClient public class ApiGatewayApp { public static void main(String[] args) { SpringApplication.run(ApiGatewayApp.class,args); } }
Introduce Eureka client configuration
application. Modify uri attribute in YML: uri: lb: / / service name
server: port: 80 spring: application: name: api-gateway-server cloud: # Gateway configuration gateway: # Routing configuration: forwarding rules routes: #Gather. # id: unique identification. The default is a UUID # uri: forwarding path # Predictions: conditions used to request matching rules for gateway paths # Filters: to configure local filters - id: gateway-provider # Static routing # uri: http://localhost:8001/ # Dynamic routing uri: lb://GATEWAY-PROVIDER predicates: - Path=/goods/**
4.5 gateway microservice name configuration
application. Configuring microservice name in YML
# Microservice name configuration discovery: locator: enabled: true # Set to true to add a microservice name before the request path lower-case-service-id: true # Lowercase allowed
4.6-Gateway-filter
4.6.1 - Filters - General
-
The Gateway supports the filter function to intercept requests or responses and complete some general operations.
-
Gateway provides two filter modes: "pre" and "post"
The pre filter is implemented before forwarding. It can perform parameter verification, permission verification, traffic monitoring, log output, protocol conversion, etc.
The post filter is executed before the response. It can modify the response content, response header, log output, traffic monitoring, etc. -
Gateway also provides two types of filters
Gateway filter: local filter for a single route
GlobalFilter: Global filter for all routes
4.6.2 - local filter
- Gateway filter is a local filter for a single route.
- A large number of built-in local filters are provided in the Spring Cloud Gateway component to filter requests and responses.
- Following the idea that the Convention is greater than the configuration, you only need to configure the local filter name in the configuration file and specify the corresponding value to make it effective.
Refer to gateway built-in filter factory for specific configuration md
Test configuration
api-gateway-server application.yml
server: port: 80 spring: application: name: api-gateway-server cloud: # Gateway configuration gateway: # Routing configuration: forwarding rules routes: #Gather. # id: unique identification. The default is a UUID # uri: forwarding path # Predictions: conditions used to request matching rules for gateway paths # Filters: to configure local filters - id: gateway-provider # Static routing # uri: http://localhost:8001/ # Dynamic routing uri: lb://GATEWAY-PROVIDER predicates: - Path=/goods/** filters: - AddRequestParameter=username,zhangsan
Add the username parameter to findOne in GoodsController in gateway provider module
public Goods findOne(@PathVariable("id") int id,String username){ System.out.println(username); //If id == 1, an exception occurs= 1 normal access if(id == 1){ //1. Make an exception int i = 3/0; } /*try { //2. Sleep for 2 seconds Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }*/ Goods goods = goodsService.findOne(id); goods.setTitle(goods.getTitle() + ":" + port);//Set the port number to the product title return goods; }
4.6.3 - Global filter
-
GlobalFilter global filter, which does not need to be configured in the configuration file, is loaded during system initialization and acts on each route.
-
The core functions of Spring Cloud Gateway are also completed through the built-in global filter.
-
To customize a global filter:
- Define classes that implement GlobalFilter and Ordered interfaces
- Replication method
- Complete logical processing
MyFilter
package com.itheima.gateway.filter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class MyFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { System.out.println("Custom global filter implemented~~~"); return chain.filter(exchange);//Release } /** * Filter sorting * @return The smaller the value, the earlier the execution */ @Override public int getOrder() { return 0; } }