In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/03 Report--
Basic introduction
Spring Cloud Gateway (replaced by SCG below), as its name implies, is a gateway product officially produced by Spring and a sub-project of Spring Cloud.
This project provides a library for building an API Gateway on top of Spring MVC. Spring Cloud Gateway aims to provide a simple, yet effective way to route to APIs and provide cross cutting concerns to them such as: security, monitoring/metrics, and resiliency.
The official introduction mainly highlights the simplicity and effectiveness of routing functions, while providing good support in terms of security, monitoring and scalability. After all, it depends on the big tree of Spring Cloud.
Architecture understanding
This is a schematic diagram of the working principle of the official website, from which we can see that SCG mainly acts as a reverse agent in the whole process. After the client request arrives at SCG, SCG routes the request to Web Handler,Web Handler through Handler Mapping, then processes the original request through Filter, and finally sends it to the proxied server.
Technical comparison
Before studying SCG, we found that there is a mature API suite Spring Cloud Netflix under Spring Cloud, which provides features such as Service Registration Discovery (Eureka), fuse (Hystrix), Intelligent routing (Zuul) and client load balancing (Ribbon), among which we need the routing function Zuul.
So why does Spring Cloud develop its own Gateway project for routing after integrating a routing function? Let's take a look at some of their comparisons, because Spring Cloud only integrates with Zuul1.0, so the comparison also focuses on Zuul1.0 and SCG.
Connection mode supports server function Zuul1.0Servlet APITomcat,undertow basic routing rules, only supports Path routing SCGReactorNetty more routing rules, and can support rich predict definitions such as header,cookie,query,method.
From the above comparison, SCG based on Project Reactor can get better throughput, which is equivalent to the optimization of Zuul in terms of function, and more flexible configuration can meet almost all gateway routing needs.
Although Zuul2.0 is also based on Netty development, and enhanced routing and filter features, but his many ticket skips finally made Spring decide to build a gateway routing product, and said that he will not integrate Zuul2.0 into the future Spring Cloud, which is an interesting story.
Gateway practice
Next we actually implement a gateway, combined with the problems encountered in the process to familiarize ourselves with the features of SCG.
Initialization
Let's create a new Spring Boot-based Maven project and add SCG dependencies, mainly the following two
Org.springframework.cloud spring-cloud-starter-gateway org.springframework.boot spring-boot-starter-webflux
The latest version of Spring Boot Release (2.1.4) and the Spring Cloud branch Greenwich that supports 2.1 are selected here.
Finally, create a SpringBootApplication, refer to the Demo on the home page and remove the content related to Hystrix and RateLimit to run (https://spring.io/projects/spring-cloud-gateway).
Dynamic routing
Certainly not with a Demo, our gateway is actually put into production, after analyzing the actual demand, we found that the first urgently needed function is dynamic routing.
Two ways of routing configuration are provided in the document
Through java API
Build the following directly through RouteLocatorBuilder:
Builder.routes () .route ("path_route", r-> r.path ("/ get") .uri ("http://httpbin.org")).build()
Through the configuration file
The route is built from the YAML file as follows:
Spring: cloud: gateway: routes:-id: host_route uri: https://example.org predicates:-Path=/foo/ {segment}, / bar/ {segment}
However, there is a scenario of dynamic routing in the actual demand, and the above two methods obviously can not meet the demand.
By looking at the source code, it is found that SCG loading routing is implemented through the RouteDefinitionLocator interface, with the following default implementation (the box can be ignored temporarily, which is our own implementation):
In GatewayAutoConfiguration, CompositeRouteDefinitionLocator is specified as the entry point for loading the route definition through Primary, and all RouteDefinitionLocator proxies are loaded through the combined mode. Finally, all the definitions are loaded through the getRouteDefinitions method of CompositeRouteDefinitionLocator.
Bean @ Primary public RouteDefinitionLocator routeDefinitionLocator (List routeDefinitionLocators) {return new CompositeRouteDefinitionLocator (Flux.fromIterable (routeDefinitionLocators));} public class CompositeRouteDefinitionLocator implements RouteDefinitionLocator {private final Flux delegates; public CompositeRouteDefinitionLocator (Flux delegates) {this.delegates = delegates;} @ Override public Flux getRouteDefinitions () {return this.delegates.flatMap (RouteDefinitionLocator::getRouteDefinitions);}}
Through the interpretation of the source code, we find that if we need to define a new route loading method, we only need to add an implementation of RouteDefinitionLocator. In practice, in order to facilitate routing updates, we imitate the existing implementation.
Implement it with InMemoryRouteDefinitionRepository. The class diagram is as follows:
We complete the extension of RouteDefinitionRepository by adding an abstract class. In the abstract class, we implement the basic get, save, delete methods, and add the refresh method to refresh the cache. The implementation of the cache refers to the implementation of InMemory.
When we need to expand, we can add our own configure loader by inheriting AbstractRoutConfigure, and then inject it through Configuration:
The final implementation effect is that after we change the configuration through the database, we can complete the dynamic refresh of the route by calling the refresh method through the restful interface.
Service routing
With the basic implementation of dynamic routing above, the configuration in our database looks like this
But we are going to do micro-services and cluster gateways, so it is obviously not possible to write addresses directly.
In response to this situation, SCG provides a URI format: lb://main-service, where main-service is the name of our micro services in the registry.
When URI starts with lb, the client implementation corresponding to zookeeper,consul,eureka is looked for when doing URI parsing. We used eureka and added the following configuration to the database
In this way, we can successfully proxy the interface provided by the microservice.
Fault-tolerant management
Fault-tolerant management is considered from the following two aspects
1, the route is not defined
For the case that the route is not found, provide meaningful error information for effective feedback.
The implementation layer is mainly by defining a NotFound route, by setting order to ensure that NotFound routing is executed after all routes, so that when all routes do not match, they will be routed to NotFound routes, thus feedback meaningful error messages.
Database definition
Code part:
/ * * error message when no route is found * / @ RequestMapping (value = "/ notfoundcontroller") public Mono notFoundController () {Map res = new HashMap (); res.put ("code", "- 404"); res.put ("data", "route definition notfound"); return Mono.just (res);}
2, fuse Hystrix
Fuses are mainly used in use scenarios such as request timeouts and server errors. SCG provides the integration of Hystrix. We only need to configure default filter in the YAML configuration file and add the implementation of fallbackUri.
YAML
Spring: cloud: gateway: default-filters:-name: Hystrix args: name: fallbackcmd fallbackUri: forward:/fallbackcontroller
FallbackUri
/ * * Service degradation address corresponding to the circuit breaker, handle request failure * / @ RequestMapping (value = "/ fallbackcontroller") public Mono fallBackController () {Map res = new HashMap (); res.put ("code", "- 100"); res.put ("data", "service not available"); return Mono.just (res);}
Through the configuration of the above two points, we can get the corresponding error messages in the case of request errors such as timeout and service downtime, which ensures the robustness of the gateway service.
Current limiting mechanism
The current limiting mechanism (Rate Limiter) used by SCG is based on the token bucket algorithm, so let's first take a look at the token bucket algorithm.
As you can see from the figure above, the main data structure of the token bucket algorithm is a buffer. The buffer is filled with tokens generated at a uniform speed, while the actual traffic is equivalent to consumers consuming tokens in the buffer.
Let's combine the implementation in SCG to see how the token bucket algorithm restricts the current.
SCG needs to introduce spring-boot-starter-data-redis-reactive to use RateLimiter, so the token bucket implementation of SCG is based on Redis, which can meet the distributed requirements.
In the process of using SCG, you need to set three parameters: replenishRate, burstCapacity and KeyResolver.
replenishRate represents the rate of bottling, that is, the rate at which tokens are generated
burstCapacity refers to the high burst capacity in an instant, and the official documentation explains that it is the maximum traffic allowed in a second, adding the number of tokens that can be held in the token bucket.
KeyResolver is easy to understand. Through the definition of key, you can clearly specify the level of current limit, user level or IP level, and so on.
According to the understanding of burstCapacity, only when replenishRate and burstCapacity are equal, that is, when request processing is basically uniform, burstCapacity represents the maximum traffic allowed in a second, otherwise it is interpreted as the capacity of the token bucket is more appropriate.
The code is implemented mainly through RedisRateLimiter.class and request_rate_limiter.lua files, while the main logic is realized through script files.
Here, we mainly get the parameters passed by java, and calculate that the logic of ttl,ttl is twice the time it takes to fill the bucket.
The above code is the key to achieving current limit. Each time, the filled token is calculated by the interval between the current time and the last refresh time. Only the number of populated tokens > = requested meets the conditions to allow the token to be obtained.
When the new request gets the token, update the number of tokens in the token bucket and the last refresh time.
In the actual citation, we set rate and capacity according to the pressure of our server, through constant adjustment to find the balance of throughput and load.
Log configuration
In addition to the basic logback configuration, you need to add the configuration of access_log. According to the official documentation, we need to add the configuration of logger and appender to the logback configuration file.
Access_log.log msg%n
As shown above, the AccessLog of the logger that receives the netty is defined and sent to the accessLog Appender through an asynchronous transmitter.
It should be noted that the configuration of Netty AccessLog will not be supported until after reactor-netty0.7.9, so before using this feature, we need to make sure that the version of our netty meets the requirements. The spring version currently used in the project is as follows, and the corresponding reactor-netty version is 0.8.6.
With so many configurations, the access.log file is still empty because you missed an important step:
Add-Dreactor.netty.http.server.accessLogEnabled=true to the startup parameters. Note that this property is a java system property rather than a spring configuration property, that is, it can only be injected through startup parameters.
Summary
We understand the background of SCG through some simple introduction, and then understand the architecture concept and implementation details of SCG step by step through the actual gateway construction practice.
Through the dynamic routing part, we have witnessed the scalable architecture of SCG. In the service routing and fault tolerant management part, we mainly integrate with the existing components of Spring Cloud (eureka, hystrix). In the current limiting mechanism part, we understand the current limiting algorithm based on token bucket and how to realize distributed system current limiting with Redis. In the log configuration part, it is mainly combined with the log mechanism of Netty to complete the access log configuration of the gateway.
We haven't used all the features of SCG in our practice, but it's enough for our own API gateway in the current situation.
Peripheral tidbits HikariDataSource
When starting the spring boot program, I found the following two sentences
2019-05-20 13 HikariPool-1 5615 32381 [main] INFO com.zaxxer.hikari.HikariDataSource-HikariPool-1-Starting...
2019-05-20 13 HikariPool-1 56 main 32875 INFO com.zaxxer.hikari.HikariDataSource-HikariPool-1-Start completed.
So I went to see who this HikariDataSource is with curiosity.
I was shocked to see that this thing I had never heard of was the default connection pool of spring boot. As a connection pool, its performance could surpass that of druid. Limited to space, we will open another article to study it.
How to handle multiple locator
In the previous source code analysis, we saw that RouteDefinitionLocator is the proxy mode, which loads all the route defined in the proxy locator through a combiner. The core code is:
So when we define multiple locator (such as MySql's locator, Json's locator), how does SCG merge these locator?
Through GatewayAutoConfiguration.class, we find that the RouteLocator defined as Primary is CachingRouteLocator.
In CachingRouteLocator, all the route obtained by locator are sorted through the decorator mode, based on the order field.
To sum up, if more than one routeDefinitionLocator is defined, the route in it is sorted according to order, and if order is not defined, the default order is 0.
After the sorting is completed, the requests are matched one by one in order, and if they are satisfied, the matching will not continue. That is to say, the smaller the order defined globally, the higher the priority, no matter which locator it comes from.
Hystrix circuit short-circuited and is OPEN error
This error occurs after the circuit breaker is configured and occurs when the configured fallbackuri is not defined or cannot be matched. The cause in our practice is that the method of fallbackuri is configured as GET, and the request that actually caused the error is sent through POST.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.