The article has been included in my Github collection. Welcome Star: https://github.com/yehongzhi/learningSummary
Write in front
The previous article wrote the Gateway's predict (for routing and forwarding), so this article introduces another main core, that is, filter.
What does the filter do? What is the workflow like? See the figure below:

It is obvious from the figure that Filter is required before and after requesting back-end services. Therefore, the role of Filter is clear. Parameter verification, traffic monitoring, logging and modifying request content can be done in prefilter (request pre-processing), and response content can be modified in postfilter (request post-processing).
filter
Filter s are divided into local and global types:
- Local filter (subclass of gatewayfilter) acts on a single route. If you need to use global routing, you need to configure Default Filters.
- Global filter (a subclass of globalfilter) does not need to configure routes. System initialization works on all routes.
Local filter
Spring cloud gateway has many built-in routing filters, which are generated by the factory class of GatewayFilter.
AddRequestParameter GatewayFilter
This filter can add parameters to the request.
For example, I have an interface with a userName parameter in the consumer service. I want to add a userName=yehongzhi parameter to the gateway when requesting routing forwarding.
@RequestMapping(value = "/getOrder",method = RequestMethod.GET) public String getOrder(@RequestParam(name = "userName") String userName) { return "Gets the incoming user name:" + userName; }
The configuration is as follows:
spring: cloud: gateway: routes: - id: add_request_parameter uri: http://localhost:8081/getOrder predicates: - Method=GET - Path=/getOrder filters: - AddRequestParameter=userName,yehongzhi
So when I request a gateway, enter http://localhost:9201/getOrder , we can see the default userName.

StripPrefix GatewayFilter
This filter removes a specified number of path prefixes.
For example, if I want to remove the first level of the path prefix of the request gateway, I can configure it as follows:
spring: cloud: gateway: routes: - id: strip_prefix_gateway uri: http://localhost:8081 predicates: - Path=/consumer/** filters: - StripPrefix=1
When requesting a path http://localhost:9201/consumer/getDetail/1 , results can be obtained.

Equivalent to request http://localhost:8081/getDetail/1 , the result is the same.

PrefixPath GatewayFilter
In contrast to the previous filter, this filter adds a specified prefix to the original path.
spring: cloud: gateway: routes: - id: prefix_path_gateway uri: http://localhost:8081 predicates: - Path=/getUserInfo/** filters: - PrefixPath=/consumer
When requested http://localhost:9201/getUserInfo/1 When, follow the request http://localhost:8081/consumer/getUserInfo/1 It's the same.


Hystrix GatewayFilter
Of course, the gateway has a fusing mechanism, so the filter integrates Hystrix to realize the fusing function. How to use it? First, we need to introduce the maven dependency of Hystrix.
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency>
Add the fallback() method to the gateway service
@RestController public class FallBackController { @RequestMapping("/fallback") public String fallback(){ return "The system is busy, please try again later!"; } }
The gateway service is configured as follows. When there is an error in forwarding the GET request route, the service degradation will be triggered:
spring: cloud: gateway: routes: - id: hystrix_filter uri: http://localhost:8081 predicates: - Method=GET filters: - name: Hystrix args: name: fallbackcmd fallbackUri: forward:/fallback
At this time, we stop the service of 8081, so that the gateway cannot request the corresponding service, thus triggering service degradation.

RequestRateLimiter GatewayFilter
The filter can provide the function of limiting the flow. The RateLimiter implementation is used to determine whether to allow the current request to continue. If the request is too large, the HTTP 429- too many request status will be returned by default. How? First, we have to introduce Maven dependency.
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency>
Then add a configuration class.
@Configuration public class LimiterConfig { /** * ip Current limiter */ @Bean public KeyResolver ipKeyResolver() { return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName()); } }
Then configure the following to add a current limiting policy to GET requests:
spring: cloud: gateway: routes: - id: hystrix_filter uri: http://localhost:8081 predicates: - Method=GET filters: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 1 #The number of requests allowed to be processed per second redis-rate-limiter.burstCapacity: 2 #Maximum number of requests processed per second key-resolver: "#{@ipKeyResolver}" #Current limiting policy, Bean corresponding to the policy redis: port: 6379 host: 192.168.1.5 #redis address
Then start the service and continuously request the address http://localhost:9201/getDetail/1 , it will trigger current limiting and report 429 error.

Because there are too many built-in filters, we won't list them one by one here. Interested students can learn by themselves on the official website.
Custom local filter
If the built-in local filter cannot meet the requirements, we have to use a custom filter. How to use it? As an example, we customize a filter for the white list. Only those whose userName is in the white list can access it. Those who are not in the white list will return a 401 error code (Unauthorized).
The local filter needs to implement the GatewayFilter and Ordered interfaces. The code is as follows:
public class WhiteListGatewayFilter implements GatewayFilter, Ordered { //Whitelist collection private List<String> whiteList; //Initialize whitelist through constructor WhiteListGatewayFilter(List<String> whiteList) { this.whiteList = whiteList; } @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String userName = exchange.getRequest().getQueryParams().getFirst("userName"); //The white list is not empty, and the userName is included in the white list before you can access it if (!CollectionUtils.isEmpty(whiteList) && whiteList.contains(userName)) { return chain.filter(exchange); } //If the whitelist is empty or userName is not in the whitelist, 401 is returned exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } //Priority. The smaller the value, the higher the priority @Override public int getOrder() { return 0; } }
Then define a filter factory and inject it into the Spring container. The code is as follows:
@Component public class WhiteListGatewayFilterFactory extends AbstractConfigurable<WhiteListGatewayFilterFactory.Config> implements GatewayFilterFactory<WhiteListGatewayFilterFactory.Config> { private static final String VALUE = "value"; protected WhiteListGatewayFilterFactory() { super(WhiteListGatewayFilterFactory.Config.class); } @Override public List<String> shortcutFieldOrder() { return Collections.singletonList(VALUE); } @Override public GatewayFilter apply(Config config) { //Get configured whitelist String whiteString = config.getValue(); List<String> whiteList = new ArrayList<>(Arrays.asList(whiteString.split(","))); //Create an instance of WhiteListGatewayFilter and return return new WhiteListGatewayFilter(whiteList); } //Used to receive configuration parameters public static class Config { private String value; public String getValue() { return value; } public void setValue(String value) { this.value = value; } } }
Finally, we can add the following configuration in the application.yaml configuration file:
spring: cloud: gateway: routes: - id: white_list_filter uri: http://localhost:8081 predicates: - Method=GET filters: - WhiteList=yehongzhi #The white list is configured after the equal sign, separated by commas
Then start the project. First request localhost:9201/getDetail/1 without userName. 401 will be returned as expected and cannot be accessed.

Request an address with userName=yehongzhi http://localhost:9201/getDetail/1?userName=yehongzhi is in the white list, so it can be accessed normally.

Global filter
The global filter acts on all routes during system initialization and does not need to be configured separately. The interface definition class of the global filter is GlobalFilter, and the Gateway itself has many built-in filters. Let's open the class diagram to see:

Let's introduce some representative ones, such as the global filter LoadBalancerClientFilter for load balancing.
LoadBalancerClientFilter
The filter will resolve to URIs starting with lb: / /, for example:
spring: application: name: api-gateway cloud: nacos: discovery: server-addr: 127.0.0.1:8848 service: ${spring.application.name} gateway: routes: - id: consumer uri: lb://consumer # uses the lb protocol. consumer is the service name. IP address configuration is no longer used order: 1 predicates: - Path=/consumer/**
The global filter will get the service name consumer, and then get the ServiceInstance service instance through LoadBalancerClient. Reassemble the requested url according to the obtained service instance.
This is an example of a global filter application. It works globally and does not need to be configured. Next, let's explore the custom global filter. Suppose you need to count the total number of times a user's IP address accesses the gateway. What should you do?
Custom global filter
To customize the global filter, you need to implement the GlobalFilter interface and the Ordered interface.
@Component public class IPAddressStatisticsFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { InetSocketAddress host = exchange.getRequest().getHeaders().getHost(); if (host == null || host.getHostName() == null) { exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST); return exchange.getResponse().setComplete(); } String hostName = host.getHostName(); AtomicInteger count = IpCache.CACHE.getOrDefault(hostName, new AtomicInteger(0)); count.incrementAndGet(); IpCache.CACHE.put(hostName, count); System.out.println("IP Address:" + hostName + ",Number of visits:" + count.intValue()); return chain.filter(exchange); } @Override public int getOrder() { return 10101; } } //Cache for save times public class IpCache { public static final Map<String, AtomicInteger> CACHE = new ConcurrentHashMap<>(); }
Start the project, then request the service, and you can see the console print results.
IP Address: 192.168.1.4,Number of visits: 1 IP Address: 192.168.1.4,Number of visits: 2 IP Address: 192.168.1.4,Number of visits: 3 IP Address: localhost,Number of visits: 1 IP Address: localhost,Number of visits: 2 IP Address: localhost,Number of visits: 3 IP Address: 192.168.1.4,Number of visits: 4
summary
The functions of the service gateway are basically realized through the predictions in the previous article and the Filters in this article, including routing forwarding, permission interception, traffic statistics, traffic control, service fusing, logging and so on. Therefore, gateway service is a very important part of microservice architecture. Many front-line Internet companies will also develop service gateways by themselves. Therefore, mastering the service gateway is a necessary skill for back-end development. Thank you for reading.