赞
踩
- <?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>01-sca</artifactId>
- <groupId>com.jt</groupId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
-
- <artifactId>sca-gateway</artifactId>
-
- <properties>
- <maven.compiler.source>8</maven.compiler.source>
- <maven.compiler.target>8</maven.compiler.target>
- </properties>
- <dependencies>
- <!--添加gateway依赖:假如依赖下载不下来:
- 1)保证网络没有问题(手机网络,公司网络)
- 2)保证maven配置正确(maven软件,远程仓库)
- 3)本地库(本地库中尽量不要存在同一个资源的多个版本)
- -->
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-gateway</artifactId>
- </dependency>
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
- </dependency>
-
- <!--拓展:基于如下依赖中的API可以实现对象与json字符串之间转换-->
- <dependency>
- <groupId>com.google.code.gson</groupId>
- <artifactId>gson</artifactId>
- <version>2.8.5</version>
- </dependency>
-
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
- </dependency>
- <dependency>
- <groupId>com.alibaba.cloud</groupId>
- <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
-
- </dependencies>
-
- </project>
- server:
- port: 9000
- spring:
- application:
- name: sca-gateway
- cloud:
- nacos:
- discovery:
- server-addr: localhost:8848
- sentinel:
- transport:
- dashboard: localhost:8180
- #port: 8719
- eager: true #服务启动时会会向sentinel控制台发送心跳,为我们的应用创建菜单
- gateway: # API Gateway (负责API管理)
- discovery:
- locator:
- enabled: true #开启基于服务名获取服务实例的功能(基于服务名创建路由)
- routes: #网关路由配置
- - id: router01 #http://localhost:9000/nacos/provider/echo/hello
- #uri: http://localhost:8081
- uri: lb://sca-provider #lb表示负载均衡,底层默认使用ribbon实现
- predicates: #定义请求规则(请求需要按照此规则设计)
- - Path=/nacos/provider/echo/** #请求路径设计
- #- After=2021-08-23T13:59:59.789+08:00[Asia/Shanghai]
- #- Header=X-Request-Id, \d+ #\d+表示任何一个数字
- #- Method=GET
- #- Query=pageSize,\d+
- filters:
- - StripPrefix=1 #转发之前去掉path中第一层路径,例如nacos
- #- AddRequestHeader=X-Request-Foo, Bar
- #- AddRequestParameter=foo, hello
-
- #自己定义白名单路径
- white:
- prefix: /nacos
-
-
- # 假如希望调整负载均衡算法,可参考如下配置方式
- sca-provider: #这个名字为指定的服务名
- ribbon:
- #NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule
- NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
- id,路由标识符,区别于其他 Route。
- uri,路由指向的目的地 uri,即客户端请求最终被转发到的微服务。
- predicate,断言(谓词)的作用是进行条件判断,只有断言都返回真,才会执行路由。
- filter,过滤器用于修改请求和响应信息。
此类型的断言根据时间做判断,主要有三个:
1) AfterRoutePredicateFactory:判断请求日期是否晚于指定日期
2) BeforeRoutePredicateFactory:判断请求日期是否早于指定日期
3) BetweenRoutePredicateFactory:判断请求日期是否在指定时间段内
-After=2020-12-31T23:59:59.789+08:00[Asia/Shanghai]
当且仅当请求时的时间After配置的时间时,才转发该请求,若请求时的时间不是After配置的时间时,则会返回404 not found。时间值可通过ZonedDateTime.now()获取.
判断请求Header是否具有给定名称且值与正则表达式匹配。例如:
-Header=X-Request-Id, \d+
MethodRoutePredicateFactory接收一个参数,判断请求类型是否跟指定的类型匹配。例如:
-Method=GET
接收两个参数,请求param和正则表达式, 判断请求参数是否具 有给定名称且值与正则表达式匹配。例如:
-Query=pageSize,\d+
过滤器(Filter)就是在请求传递过程中,对请求和响应做一个处理。Gateway 的Filter从作用范围可分为两种:GatewayFilter与GlobalFilter。其中:
GatewayFilter:应用到单个路由或者一个分组的路由上。
GlobalFilter:应用到所有的路由上
基于AddRequestHeaderGatewayFilterFactory,为原始请求添加Header。
- spring:
- cloud:
- gateway:
- routes:
- - id: add_request_header_route
- uri: https://example.org
- filters:
- - AddRequestHeader=X-Request-Foo, Bar
基于AddRequestParameterGatewayFilterFactory,为原始请求添加请求参数及值,
- spring:
- cloud:
- gateway:
- routes:
- - id: add_request_parameter_route
- uri: https://example.org
- filters:
- - AddRequestParameter=foo, bar
基于PrefixPathGatewayFilterFactory,为原始的请求路径添加一个前缀路径
- spring:
- cloud:
- gateway:
- routes:
- - id: prefixpath_route
- uri: https://example.org
- filters:
- - PrefixPath=/mypath
基于RequestSizeGatewayFilterFactory,设置允许接收最大请求包的大小
- spring:
- cloud:
- gateway:
- routes:
- - id: request_size_route
- uri: http://localhost:8080/upload
- predicates:
- - Path=/upload
- filters:
- - name: RequestSize
- args:
- # 单位为字节
- maxSize: 5000000
- package com.jt.config;
-
- import com.google.gson.Gson;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.cloud.gateway.filter.GatewayFilterChain;
- import org.springframework.cloud.gateway.filter.GlobalFilter;
- import org.springframework.core.Ordered;
- import org.springframework.core.io.buffer.DataBuffer;
- import org.springframework.http.server.reactive.ServerHttpRequest;
- import org.springframework.http.server.reactive.ServerHttpResponse;
- import org.springframework.stereotype.Component;
- import org.springframework.web.server.ServerWebExchange;
- import reactor.core.publisher.Mono;
-
- import java.util.HashMap;
- import java.util.Map;
-
- /**
- * 自定义的全局过滤器,作用域所有路由
- */
- @Component
- public class AuthGatewayFilter implements GlobalFilter, Ordered {
-
- @Value("${white.prefix}")
- private String whitePrefix;
- /**你的业务可以写到这个filter方法内部
- * @param exchange 基于此对象可以获取请求和响应对象
- * @param chain 这个对象指向了一个过滤链(这个链中有多个过滤器)
- * */
- @Override
- public Mono<Void> filter(ServerWebExchange exchange,
- GatewayFilterChain chain) {
- //1.获取请求对象
- ServerHttpRequest request = exchange.getRequest();
- //2.获取请求数据
- String path = request.getURI().getPath();
- System.out.println("path="+path);
- //String username=request.getQueryParams().getFirst("username");
- //3.对请求数据进行处理
- //例如判定请求的path是否在我们允许的范围之内
- System.out.println("whitePrefix="+whitePrefix);
- if(!path.startsWith(whitePrefix)) {//判断路径的前缀
- //获取响应对象
- ServerHttpResponse response = exchange.getResponse();
- //设置响应状态码,这里的值为502
- //response.setStatusCode(HttpStatus.BAD_GATEWAY);
- //结束当前请求
- //return response.setComplete();//直接结束
- //假如希望响应一些具体内容到客户端
- //String content="request failure";
- //byte[] bytes=content.getBytes();
- Map<String,Object> map=new HashMap<>();
- map.put("message","request failure");
- map.put("status",502);
- //将map对象转换为json字符串?
- //String jsonStr="{\"message\":\"request failure\",\"status\":502}";
- Gson gson=new Gson();
- String jsonStr=gson.toJson(map);//将map对象转换json格式字符串.
- byte[] bytes=jsonStr.getBytes();
- DataBuffer dataBuffer=
- response.bufferFactory().wrap(bytes);
- return response.writeWith(Mono.just(dataBuffer));
- //Spring WebFlux,Mono是一个可以封装0个或1个元素的序列对象.
- }
- //4.返回响应结果
- return chain.filter(exchange);//将请求交给下一个过滤器进行处理
- }
- @Override
- public int getOrder() {
- return Ordered.HIGHEST_PRECEDENCE;
- }
- }
网关是所有请求的公共入口,所以可以在网关进行限流,而且限流的方式也很多,我们采用Sentinel组件来实现网关的限流。Sentinel支持对SpringCloud Gateway、Zuul等主流网关进行限流。参考网址如下:
https://github.com/alibaba/spring-cloud-alibaba/wiki/Sentinel
启动网关项目,检测sentinel控制台的网关菜单。
启动时,添加sentinel的jvm参数,通过此菜单可以让网关服务在sentinel控制台显示不一样的菜单,代码如下。
-Dcsp.sentinel.app.type=1
基于请求属性限流
新建api分组
新建分组流控规则,如图所示:
- package com.jt.config;
-
- import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.BlockRequestHandler;
- import com.alibaba.csp.sentinel.adapter.gateway.sc.callback.GatewayCallbackManager;
- import com.alibaba.fastjson.JSON;
- import com.google.gson.Gson;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.http.server.reactive.ServerHttpResponse;
- import org.springframework.web.reactive.function.server.ServerResponse;
- import org.springframework.web.server.ServerWebExchange;
- import reactor.core.publisher.Mono;
-
- import java.util.HashMap;
- import java.util.Map;
-
- @Configuration
- public class GatewayConfig {
- public GatewayConfig(){
- GatewayCallbackManager.setBlockHandler(new BlockRequestHandler() {
- @Override
- public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
- ServerHttpResponse response = serverWebExchange.getResponse();
- Map<String,Object> map=new HashMap<>();
- map.put("state",429);
- map.put("message","two many request");
- //String jsonStr= JSON.toJSONString(map);
- Gson gson = new Gson();
- String s = gson.toJson(map);
- return ServerResponse.ok().body(Mono.just(s), String.class);
- }
- });
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。