前置内容
(1)、微服务理论入门和手把手带你进行微服务环境搭建及支付、订单业务编写
(2)、SpringCloud之Eureka服务注册与发现
(3)、SpringCloud之Zookeeper进行服务注册与发现
(4)、SpringCloud之Consul进行服务注册与发现
(5)、SpringCloud之Ribbon进行服务调用
(6)、SpringCloud之OpenFeign进行服务调用
(7)、SpringCloud – Hystrix断路器
1. 是什么
Spring Cloud Gateway
使用的Webflux
中的reactor-netty
响应式编程组件,底层使用了Netty
通讯框架。2. 能干嘛
3. 在微服务架构中的位置
4. 选择Gateway的原因
neflix
不太靠谱,zuul2.0
一直跳票,迟迟不发布Spring Cloud Gateway
是基于Spring Framework 5
,Project Reactot
和Spring Boot 2.0
进行构建,可以实现动态路由,可以堆路由指定断言和过滤器;集成Hystrix
的断路器功能;集成Spring Cloud
服务发现功能;易于编写的断言和过滤器;同时支持请求限流功能和支持路径重写。Zuul 1.x
是一个基于阻塞I/O
的网关,Spring Cloud Gateway
是基于Spring Framework 5
,Project Reactot
和Spring Boot 2.0
进行构建;Spring Cloud Gateway
还支持WebSocket
,并且与Spring
紧密集成拥有更好的开发体验。ID
,目标URI
,一系列的断言和过滤器组成,如果断言为true
则匹配该路由。java8
的java.util.function.Predicate
开发人员可以匹配HTTP
请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由。Spring
框架中GatewayFilter
的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。web
请求,通过一些匹配条件,定位到真正的服务节点。并在这个转发过程的前后,进行一些精细化控制。predicate
就是我们的匹配条件;而filter
,就可以理解为一个无所不能的拦截器。有了这两个元素,再加上目标uri
,就可以实现一个具体的路由了。Spring Cloud Gateway
发出请求。然后在Gateway Handler Mapping
中找到与请求相匹配的路由,将其发送到Gateway Web Handler
。handler
再通过指定的过滤链来将请求发送到我们实际的服务执行业务逻辑,然后返回。过滤器之间用虚线分开是因为过滤器可能会在发送请求之前(pre
)或之后(post
)执行业务逻辑。pre
类型的过滤器可以做参数检验、权限监控、日志输出、协议转换等,在post
类型的过滤器可以做响应内容、响应头的修改,日志的输出,流量监控等有着非常重要的作用。1. 建Module
Module
的名称为cloud-gateway-gateway9527
。2. 改POM
<dependencies>
<!--新增gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.xiao</groupId>
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</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>
3. 改YML
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
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
4. 主启动
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class GateWayMain9527 {
public static void main(String[] args) {
SpringApplication.run(GateWayMain9527.class,args);
}
}
5. 测试结果
8001
端口进行访问,还可以通过9527
端口进行访问。1. 配置类
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class GateWayConfig {
@Bean
public RouteLocator getRoute(RouteLocatorBuilder builder){
RouteLocatorBuilder.Builder routes = builder.routes();
// 实现http://localhost:9527/guonei 跳转到 http://news.baidu.com/guonei
routes.route("path_route",r -> r.path("/guonei").uri("http://news.baidu.com/guonei")).build();
return routes.build();
}
}
2. 测试结果
http://localhost:9527/guonei
跳转到 http://news.baidu.com/guonei
1. 修改相关的yml配置文件
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
discovery:
locator:
enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由
routes:
- id: payment_routh #路由的ID,没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service
predicates:
- Path=/payment/get/** #断言,路径相匹配的进行路由
- id: payment_routh2
#uri: http://localhost:8001
uri: lb://cloud-payment-service
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
2. 测试结果
8001
和8002
这两个服务器上进行请求相应的资源。1. Predicate是什么
Predicate
就是为了实现一组匹配规则,让请求过来找到对应的Route
进行处理2. 详细配置
spring:
cloud:
gateway:
routes:
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
#- After=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] 表示要在这个时间之后才能进行访问
#- Before=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] 表示在这个时间之前
# - Between=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] , 2020-03-08T10:59:34.102+08:00[Asia/Shanghai] 表示要在这两个时间之间
#- Cookie=username,zhangshuai #并且Cookie是username=zhangshuai才能访问
#- Header=X-Request-Id, \d+ #请求头中要有X-Request-Id属性并且值为整数的正则表达式
#- Host=**.xiao.com
#- Method=GET
#- Query=username, \d+ #要有参数名称并且是正整数才能路由
1. 过滤器是什么
HTTP
请求和返回的HTTP
响应,路由过滤器只能指定路由进行使用。2. 过滤器的作用
3. 过滤器的分类
(1)、生命周期划分
pre
:在业务逻辑之前post
:在业务逻辑之后(2)、种类划分
GatewayFilter
:单一GlobalFilter
:全局1. 过滤器类的编写
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Date;
@Component
@Slf4j
public class MyLogGateWayFilter implements GlobalFilter,Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("*********come in MyLogGateWayFilter: "+new Date());
String uname = exchange.getRequest().getQueryParams().getFirst("username");
if(StringUtils.isEmpty(uname)){
log.info("*****用户名为Null 非法用户,(┬_┬)");
exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE);//给人家一个回应
return exchange.getResponse().setComplete();
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
return 0;
}
}
2. 测试结果
(1)、携带正确参数
(2)、 未携带正确参数
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/weixin_56727438/article/details/122419033
内容来源于网络,如有侵权,请联系作者删除!