Zuul不讲,放弃
Gateway 新一代网关
SpringCloud2.2.1,和Spring整合,引入许多新技术,是Zuul1.x版的替代。基于webflux框架实现的,而webflux框架底层使用了高性能的reactor模式通信框架Netty
外部请求→负载均衡→网关→微服务,可以把网关当成微服务的入口
为什么选gateway?
- neflix不太靠谱,一直跳票
- springcloud gateway具有以下特性:
基于spring 5,reactor,springboot2.0构建的
动态路由:能匹配任何请求属性
可以对路由指定断言和过滤
集成Hystrix的断路器功能
集成springcloud服务发现功能
易于编写断言和过滤器
请求限流功能
支持路径重写
路由(route): ⽹关最基础的部分,也是⽹关⽐较基础的⼯作单元。路由由⼀个ID、⼀个⽬标URL(最终路由到的地址)、⼀系列的断⾔(匹配条件判断)和Filter过滤器(精细化控制)组成。如果断⾔为true,则匹配该路由。
断⾔(predicates):参考了Java8中的断⾔java.util.function.Predicate,开发⼈员可以匹配Http请求中的所有内容(包括请求头、请求参数等)(类似于nginx中的location匹配⼀样),如果断⾔与请求相匹配则路由。
过滤器(filter):⼀个标准的Spring webFilter,使⽤过滤器,可以在请求之前或者之后执⾏业务逻辑。
过滤器可能会在发送代理请求之前(pre)或者之后(post)执⾏业务逻辑。
Filter在“pre”类型过滤器中可以做参数校验、权限校验、流量监控、⽇志输出、协议转换等,在“post”类型的过滤器中可以做响应内容、响应头的修改、⽇志的输出、流量监控等。
新建cloud-gateway-gateway9527模块
Pom:
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>com.xs.springcloud</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
Application.yml:
server:
port: 9527
spring:
application:
name: cloud-gateway
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
主启动类:
@SpringBootApplication
@EnableEurekaClient
public class GatewayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GatewayMain9527.class,args);
}
}
想要实现gateway,需要在yml中加入以下内容:
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_routh
uri: http://localhost:8001
predicates:
- Path=/payment/get/**
- id: payment_routh2
uri: http://localhost:8001
predicates:
- Path=/payment/lb/**
eureka:
instance:
hostname: cloud-gateway-service
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://eureka7001.com:7001/eureka
设置以访问8001的lb方法和get方法
启动7001,8001,9527
小坑:pom里不像以前一样,不能引入starter-web的jar包,否则会报错
输入http://localhost:8001/payment/get/1
http://localhost:9527/payment/get/1
都可以正常访问
看yml里面:
predicates:
- Path=/payment/get/**
意思是看有无这个路径的api,路由和断言结合使用,为true时访问成功,为false访问失败。
以上是第一种配置路由(yml配置文件中)的方式。
第二种是以编码的方式进行网关配置:
尝试跳转到百度国内新闻
创建config:com/xs/springcloud/config/GatewayConfig.java
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder routeLocatorBuilder){
RouteLocatorBuilder.Builder routes = routeLocatorBuilder.routes();
//访问/guonei会转到http://news.baidu.com/guonei
routes.route("path_route_xs",r ->r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
return routes.build();
}
}
访问http://localhost:9527/guonei
就能转到国内了
配置动态路由实现负载均衡:
Uri不应该写死,写死了以后不好扩展
通过微服务名实现动态路由
启动7001,8001,8002
修改yml文件
cloud:
gateway:
discovery:
locator:
enabled: true
把写死的地址修改掉:
uri: http://localhost:8001
uri: lb://cloud-payment-service
输入http://localhost:9527/payment/lb
会发现一直在8001和8002之间切换
predicate包含多种类型,可以一起使用:
包含有after、before、between、cookies、header、host、method、path、query、remoteaddr、weigth等
Predicate就是为了实现一组匹配规则,让请求过来找到对应的Route进行处理。
首先看after:
在yml的predicates下加入:
- After=2022-04-02T10:59:34.102+08:00[Asia/Shanghai]
在这之前输入网址会抱错,之后则无问题
后面的before和between是一样的操作
接着就是cookies
Cookies的断言需要两个参数,cookie name和正则表达式
学习用curl进行调试
在yml的predicates下面添加- Cookie=username,zzyy
控制台:C:\Users\78762>curl http://localhost:9527/payment/lb
输出:{"timestamp":"2022-04-03T19:02:04.628+0000","path":"/payment/lb","status":404,"error":"Not Found","message":null,"requestId":"5c58b0ac"}
再次在控制台内输入C:\Users\78762>curl http://localhost:9527/payment/lb --cookie "username=zzyy"
输出:8001和8002交替出现
接着是header,两个参数:属性和正则表达式
在yml的predicates下面添加- Header=X-Request-Id, \d+
控制台输入C:\Users\78762>curl http://localhost:9527/payment/lb -H "X-Request-Id:1234"
输出8001
后续内容查官网案例可以直接搞出来
GatewayFilter的生命周期:pre,post,种类:GatewayFilter(单一),GlobalFilter(全局)(自学,忽略)
自定义过滤:继承两个接口:GlobalFilter,Ordered
创建:com/xs/springcloud/config/GatewayConfig.java
@Slf4j
@Component
public class MyLogGateWayFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("=========================date: "+new Date());
String uname = exchange.getRequest().getQueryParams().getFirst("uname");
if(uname==null){
log.info("=======================用户名为null");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
//加载优先级,越小越优先
@Override
public int getOrder() {
return 0;
}
}
注销掉predicate中可能影响运行的配置
浏览器输入:http://localhost:9527/payment/lb?uname=z3
8001和8002相互交替
不带uname则无法正常运行
以上为65到73集的内容