当前位置:   article > 正文

springcloud gateway网关获取post请求参数,网关路由,网关限流,熔断降级等实际操作_gateway重定向post请求路由

gateway重定向post请求路由

上一篇使用了springcloud 一代网关 zullfilter 的拦截和路由,这一篇将使用springcloud新一代网关 gateway 来进行参数拦截,路由,限流,熔断等操作。

首先我们看下pom.xml ,不同版本,可能会有不同的坑,操作基于以下版本

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.0.4.RELEASE</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.hqk</groupId>
  12. <artifactId>gtwayservice</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>gtwayservice</name>
  15. <description>Demo project for Spring Boot</description>
  16. <properties>
  17. <java.version>1.8</java.version>
  18. <spring-cloud.version>Finchley.SR2</spring-cloud.version>
  19. </properties>
  20. <dependencies>
  21. <!-- 熔断、降级 -->
  22. <dependency>
  23. <groupId>org.springframework.cloud</groupId>
  24. <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  25. </dependency>
  26. <!--reids 限流-->
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
  30. </dependency>
  31. <dependency>
  32. <groupId>org.springframework.cloud</groupId>
  33. <artifactId>spring-cloud-starter-gateway</artifactId>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.springframework.boot</groupId>
  37. <artifactId>spring-boot-starter-test</artifactId>
  38. <scope>test</scope>
  39. </dependency>
  40. </dependencies>
  41. <dependencyManagement>
  42. <dependencies>
  43. <dependency>
  44. <groupId>org.springframework.cloud</groupId>
  45. <artifactId>spring-cloud-dependencies</artifactId>
  46. <version>${spring-cloud.version}</version>
  47. <type>pom</type>
  48. <scope>import</scope>
  49. </dependency>
  50. </dependencies>
  51. </dependencyManagement>
  52. <build>
  53. <plugins>
  54. <plugin>
  55. <groupId>org.springframework.boot</groupId>
  56. <artifactId>spring-boot-maven-plugin</artifactId>
  57. </plugin>
  58. </plugins>
  59. </build>
  60. </project>

首先我们进行网关拦截,验证token session 等操作,如下图代码,

  1. package com.hqk.gtwayservice.filter;
  2. import io.netty.buffer.ByteBufAllocator;
  3. import org.springframework.cloud.gateway.filter.GatewayFilterChain;
  4. import org.springframework.cloud.gateway.filter.GlobalFilter;
  5. import org.springframework.core.Ordered;
  6. import org.springframework.core.io.buffer.DataBuffer;
  7. import org.springframework.core.io.buffer.DataBufferUtils;
  8. import org.springframework.core.io.buffer.NettyDataBufferFactory;
  9. import org.springframework.http.server.reactive.ServerHttpRequest;
  10. import org.springframework.http.server.reactive.ServerHttpRequestDecorator;
  11. import org.springframework.stereotype.Component;
  12. import org.springframework.web.server.ServerWebExchange;
  13. import reactor.core.publisher.Flux;
  14. import reactor.core.publisher.Mono;
  15. import java.net.URI;
  16. import java.nio.CharBuffer;
  17. import java.nio.charset.StandardCharsets;
  18. import java.util.Map;
  19. import java.util.concurrent.atomic.AtomicReference;
  20. @Component
  21. public class TokenFilter implements GlobalFilter, Ordered {
  22. @Override
  23. public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
  24. ServerHttpRequest serverHttpRequest = exchange.getRequest();
  25. String method = serverHttpRequest.getMethodValue();
  26. if ("POST".equals(method)) {
  27. //从请求里获取Post请求体
  28. String bodyStr = resolveBodyFromRequest(serverHttpRequest);
  29. System.out.println("bodyStr:"+bodyStr);
  30. //TODO 这里对你获取的参数进行操作,比如 token session 的验证
  31. //下面的将请求体再次封装写回到request里,传到下一级,否则,由于请求体已被消费,后续的服务将取不到值
  32. URI uri = serverHttpRequest.getURI();
  33. ServerHttpRequest request = serverHttpRequest.mutate().uri(uri).build();
  34. DataBuffer bodyDataBuffer = stringBuffer(bodyStr);
  35. Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer);
  36. request = new ServerHttpRequestDecorator(request) {
  37. @Override
  38. public Flux<DataBuffer> getBody() {
  39. return bodyFlux;
  40. }
  41. };
  42. //封装request,传给下一级
  43. return chain.filter(exchange.mutate().request(request).build());
  44. } else if ("GET".equals(method)) {
  45. Map requestQueryParams = serverHttpRequest.getQueryParams();
  46. //TODO 得到Get请求的请求参数后,做你想做的事
  47. return chain.filter(exchange);
  48. }
  49. return chain.filter(exchange);
  50. }
  51. /**
  52. * 从Flux<DataBuffer>中获取字符串的方法
  53. */
  54. private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) {
  55. Flux<DataBuffer> body = serverHttpRequest.getBody();
  56. AtomicReference<String> bodyRef = new AtomicReference<>();
  57. body.subscribe(buffer -> {
  58. CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
  59. DataBufferUtils.release(buffer);
  60. bodyRef.set(charBuffer.toString());
  61. });
  62. return bodyRef.get();
  63. }
  64. private DataBuffer stringBuffer(String value) {
  65. byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
  66. NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT);
  67. DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length);
  68. buffer.write(bytes);
  69. return buffer;
  70. }
  71. @Override
  72. public int getOrder() {
  73. return 0;
  74. }
  75. }

然后我们postman进行测试,如下图所示

这里我们完成第一步的参数拦截

接下来我们将对请求进行路由转发,这里没有注册到注册中心,直接转发服务,直接看yml配置

  1. server:
  2. port: 9999
  3. spring:
  4. cloud:
  5. gateway:
  6. routes:
  7. - id: limit_route
  8. uri: http://127.0.0.1:8801 # 已负载均衡方式转发
  9. predicates:
  10. - Path=/**/** #只漏油转发

这里只改变IP进行转发,不会改变请求地址,如需改变请求地址,则改变 Path 路径,可参考

如果项目存在高并发场景,我们可以对请求地址 或 IP 等进行限流,限流配合redis进行使用,首先加入redis配置

  1. redis:
  2. host: localhost
  3. port: 6379
  4. database: 0

然后新建一个类

  1. package com.hqk.gtwayservice.resolver;
  2. import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.stereotype.Component;
  5. import org.springframework.web.server.ServerWebExchange;
  6. import reactor.core.publisher.Mono;
  7. import java.net.InetAddress;
  8. @Component
  9. public class IpResolver implements KeyResolver{
  10. @Override
  11. public Mono<String> resolve(ServerWebExchange exchange) {
  12. String ip=exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
  13. // exchange.getRequest().getURI().toString() //获取请求地址
  14. //可以对 ip 地址 等进行过滤
  15. System.out.println("ip:"+ip);
  16. return Mono.just(ip);
  17. }
  18. }

然后在yml中配置,这样就可以根据 ip 进行限流

  1. spring:
  2. cloud:
  3. gateway:
  4. routes:
  5. - id: limit_route
  6. uri: http://47.102.192.50:8081 # http://47.102.192.50:8081 # lb://consumer-service lb 代表从注册中心获取服务,且已负载均衡方式转发
  7. predicates:
  8. - Path=/**/** #只漏油转发
  9. filters:
  10. - name: RequestRateLimiter #名称必须是RequestRateLimiter
  11. args:
  12. key-resolver: "#{@ipResolver}" #使用SpEL按名称引用bean
  13. redis-rate-limiter.replenishRate: 2 #允许用户每秒处理多少个请求
  14. redis-rate-limiter.burstCapacity: 3 #令牌桶的容量,允许在一秒钟内完成的最大请求数
  • filter 名称必须是 RequestRateLimiter
  • redis-rate-limiter.replenishRate:允许用户每秒处理多少个请求
  • redis-rate-limiter.burstCapacity:令牌桶的容量,允许在一秒钟内完成的最大请求数
  • key-resolver:使用 SpEL 按名称引用 bean

在流量过大时进行服务降级,避免请求长时间的等待,这个是在网关层进行熔断降级,不是在服务层进行熔断降级,服务层也可进行熔断降级,接下来会写,我们先看网关层的熔断降级,先写一个降级的类,返回消息

  1. package com.hqk.gtwayservice.controller;
  2. import org.springframework.web.bind.annotation.RequestMapping;
  3. import org.springframework.web.bind.annotation.RestController;
  4. import java.util.HashMap;
  5. import java.util.Map;
  6. @RestController
  7. public class DefaultHystrixController {
  8. @RequestMapping("/defaultfallback")
  9. public Map<String,String> defaultfallback(){
  10. //System.out.println("降级操作...");
  11. Map<String,String> map = new HashMap<>();
  12. map.put("resultCode","false");
  13. map.put("resultMessage","服务异常");
  14. map.put("resultObj","这里测试网关服务熔断");
  15. return map;
  16. }
  17. }

看下整个yml的配置

  1. server:
  2. port: 9999
  3. spring:
  4. cloud:
  5. gateway:
  6. routes:
  7. - id: limit_route
  8. uri: http://47.102.192.50:8081 # http://47.102.192.50:8081 # lb://consumer-service lb 代表从注册中心获取服务,且已负载均衡方式转发
  9. predicates:
  10. - Path=/**/** #只漏油转发
  11. filters:
  12. - StripPrefix=1 #表示路由时会去除一位 如 api/app/login app/login
  13. - name: RequestRateLimiter #名称必须是RequestRateLimiter
  14. args:
  15. key-resolver: "#{@ipResolver}" #使用SpEL按名称引用bean
  16. redis-rate-limiter.replenishRate: 2 #允许用户每秒处理多少个请求
  17. redis-rate-limiter.burstCapacity: 3 #令牌桶的容量,允许在一秒钟内完成的最大请求数
  18. - name: Hystrix
  19. args:
  20. name: fallbackcmd
  21. fallbackUri: forward:/defaultfallback #这里是服务降级,调用的方法
  22. redis:
  23. host: localhost
  24. port: 6379
  25. database: 0 #限流redis 端口地址 这里没有设置密码
  26. hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 3000 #超时时间 3

项目码云下载地址 

文章参考来自 天涯泪小武 纯洁的微笑 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/302114?site
推荐阅读
相关标签