1. What is an api gateway?
The so-called API gateway refers to the unified entrance of the background system. It encapsulates the internal structure of the application and provides the unified routing service to the client. Some common logic which is not related to the functions of the business itself can be implemented here, such as authentication, authentication, monitoring, routing forwarding and so on.
To put it plainly, find services through the gateway.
2. Common api gateways
Ngnix+lua
Using nginx's reverse proxy and load balancing to achieve load balancing on api servers and highly available lua is a scripting language for writing simple logic. nginx supports lua scripting Kong
Developed based on Nginx+Lua, it has high performance and stability. There are several available plug-ins (current limiting, authentication, etc.) that can be used out of the box. Problem: Only Http protocol is supported; Secondary development makes it difficult to expand freely. Provides management API s, lacking easier control and configuration.
Zuul Netflix Open Source Gateway, rich in features, developed with JAVA, is easy to secondary development problems: lack of control, unable to dynamically configure; More dependent components; Processing Http requests relies on a Web container and does not perform as well as Nginx
Spring Cloud Gateway
The gateway service Spring developed to replace Zuul is described below.
3. Steps for use
1.Spring Cloud Gateway
Spring Cloud Gateway is Spring's technology based on Spring 5.0, Spring Boot 2.0 and Project Reactor
A gateway has been developed to provide a simple and effective unified API routing management method for the micro-service architecture. Its goal is to replace
Netflix Zuul, which not only provides a unified routing method, but also provides basic gateway functionality based on the Filter chain, such as:
Full, monitoring and current limiting.
2. Advantages and disadvantages
Advantage
Powerful performance: 1.6 times the first generation gateway Zuul
Powerful: Built-in many useful functions, such as forwarding, monitoring, current limiting, etc.
Elegant design, easy to expand
shortcoming
Its implementation relies on Netty and WebFlux, is not a traditional Servlet programming model, and is costly to learn
It cannot be deployed in Servlet containers such as Tomcat, Jetty, etc. It can only be executed as a jar package
Spring Boot version 2.0 and above is required to support
3. Traditional filters
The code is as follows (example):
@WebFilter(filterName="MyFliter",urlPatterns="/api/share/*") public class MyFliter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println(""); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("filter Before entering"); filterChain.doFilter(servletRequest,servletResponse); System.out.println("filter After entering"); } @Override public void destroy() { } } //Add comments to the main program //@ServletComponentScan("filter package name")
4. Use gateway
4.1module
4.2 Add a pom dependency
The code is as follows (example):
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>springcloud_nacos</artifactId> <groupId>com.csdn</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>springcloud_gateway</artifactId> <dependencies> <!--Limiting algorithm use redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency> <!--gateway--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <!--Service Registration--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>com.csdn</groupId> <artifactId>springcloud_common</artifactId> <version>${project.version}</version> <!--gateway Responsive web Programming Patterns We want to incorporate traditional web Programming model shaving--> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </exclusion> </exclusions> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
4.3yaml Configuration
The code is as follows (example):
server: port: 7000 spring: application: name: api-gateway cloud: nacos: discovery: server-addr: localhost:8848 # Register gateway with nacos gateway: discovery: locator: enabled: true # Let gateway get service information from nacos routes: - id: share-6002 # As long as the unique identification is present uri: lb://share-6002 #Real Address order: 1 predicates: # Reason only if the condition in the assertion is met - Path=/api/share/**,/admin/share/** - id: user-6001 # As long as the unique identification is present uri: lb://user-6001 #Real address order: 1 predicates: # Reason only if the condition in the assertion is met - Path=/api/user/**,/admin/user/**
4.4 Main program opens comment@EnableDiscoveryClient
The common point between @EnableDiscoveryClient and @EnableEurekaClient is that they both enable the registry to discover and scan the service.
@EnableEurekaClient is only available for registration as Eureka;@ EnableDiscoveryClient can be another registry.
The code is as follows (example):
@SpringBootApplication @EnableDiscoveryClient public class GatewayApplication { public static void main(String[] args) { SpringApplication.run(GatewayApplication.class,args); } }
4. Implementation Process
1: Basic concepts
Route is one of the most basic components in gateway, representing a specific routing information carrier. The following information is mainly defined:
- | - |
---|---|
id | Route identifier, different from other routes |
uri | The route points to the destination uri, which is the microservice to which client requests are ultimately forwarded. |
order | For sorting between multiple routes, the smaller the number, the higher the priority of matching. |
predicate | The purpose of an assertion is to make conditional judgments, and only when all assertions return true will the route actually be executed. |
filter | Filters are used to modify request and response information. |
DispatcherHandler: Scheduler for all requests, load request distribution
RoutePredicate HandlerMapping: A routing predicate matcher that is used for routing lookups and returns the corresponding WebHandler after finding the route. DispatcherHandler traverses the Handler Mapping collection for processing in turn
FilteringWebHandler: A WebHandler that handles requests using a Filter chain list.
RoutePredicateHandlerMapping finds the route and returns the corresponding FilteringWebHandler to process the request. The FilteringWebHandler is responsible for assembling the Filter list and calling the list to process the request.
5. Assertions
Predicate (predicate) is used to make conditional judgments, and only when all the assertions return true will the route actually be executed.
An assertion is a condition under which routing forwarding can take place
Links: https://www.cnblogs.com/wgslucky/p/11396579.html.
5.1: Custom Assertions
Add Custom Assertion Class
package gateway.pradicate; import com.alibaba.nacos.common.utils.StringUtils; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import java.util.Arrays; import java.util.List; import java.util.function.Predicate; @Component public class AgeRoutePredicateFactory extends AbstractRoutePredicateFactory<AgeRoutePredicateFactory.Config> { // 1:Configuration class, used to receive corresponding parameters in the configuration file @Data @NoArgsConstructor public static class Config { private int minAge;//18 corresponds to the first parameter in the assertion configuration private int maxAge;//60 corresponds to the second parameter in the assertion configuration } // 2:Constructor public AgeRoutePredicateFactory() { super(Config.class); } //3: Read the parameter values in the configuration file and assign them to the properties in the configuration class public List<String> shortcutFieldOrder() { //The order of this location must correspond to the order of values in the configuration file return Arrays.asList("minAge", "maxAge"); } //4: Assertion logic public Predicate<ServerWebExchange> apply(Config config) { return new Predicate<ServerWebExchange>() { @Override public boolean test(ServerWebExchange serverWebExchange) { // 4.1 Receive foreground incoming age parameters String ageStr = serverWebExchange.getRequest().getQueryParams().getFirst("Age"); //4.2 First decide if it is empty if (StringUtils.isNotEmpty(ageStr)) { //3If not null, then route logic int age = Integer.parseInt(ageStr); if (age < config.getMaxAge() && age > config.getMinAge()) { return true; } else { return false; } } return false; } }; } }
Configure under routes that need to be judged
5.2: Filter
Links: https://www.cnblogs.com/fx-blog/p/11751977.html.
Classification: Local filters (acting on a route) Global filters (acting on all routes) Gateway's filters can be divided into two types from their scope of action: GatewayFilter and GlobalFilter. GatewayFilter: Applies to a single route or a grouped route.
GlobalFilter: Applies to all routes.
Examples of built-in filters:
Note Access from Gateway
Custom local filter
Add Custom Log Configuration
@Component @Slf4j public class LogGatewayFilterFactory extends AbstractGatewayFilterFactory<LogGatewayFilterFactory.Config> { //1: Configuration class receives configuration parameters @Data @NoArgsConstructor public static class Config { private boolean consoleLog; } //2: Constructor [Fixed Writing] public LogGatewayFilterFactory() { super(Config.class); } //3: Read the parameters in the configuration file and assign them to the configuration class @Override public List<String> shortcutFieldOrder() { return Arrays.asList("consoleLog"); } //4: Filter logic @Override public GatewayFilter apply(Config config) { return new GatewayFilter() { Long start = System.currentTimeMillis(); @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // Before entering the service if (config.isConsoleLog()) { log.info("{} Get into {}",new Date(), exchange.getRequest().getPath()); } // Call the service and define the logic after the service returns // Note that if at this point you just need to go into the previous validation, you can return chain without the logic after the service has finished executing. Filter (exchange) return chain.filter(exchange).then(Mono.fromRunnable(()->{ if (config.isConsoleLog()) { Long end = System.currentTimeMillis(); log.info("{} Sign out {}. Total time consumed:{}",new Date(), exchange.getRequest().getPath(),(end-start)); } })); } }; } }
Global filter
Global filters work on all routes and do not need to be configured. Global filters enable unified validation of privileges, security validation, etc.
Customize Global Filters
//Customizing global filters requires implementing the GlobalFilter and Ordered interfaces @Component public class MyGloablFilter implements GlobalFilter, Ordered { // Filtering logic @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 1 controller before entering System.out.println("Before entering MyGloablFilter"); // 2 Release return chain.filter(exchange).then(Mono.fromRunnable(() -> { // Write the logical response returned in the callback System.out.println("from controller After returning"); })); //3 Callbacks } // The smaller the number returned, the more effective it will be @Override public int getOrder() { return 0; } }