为什么要使用网关?
可以把所有的请求通过网关侧统一规范和处理,并且还可以做统一的日志、权限验证、限流、接口服务安全加固、反向代理等工作。
这个网关的作用就相当于你去医院看病,首先的到分诊台去挂号,然后在给你导流到不同的科室去看病。而不是你直接去某某科室看病,那就乱了。所以在微服务架构中网关也是必然存在的。
gateway spring社区开发的
参考
https://blog.csdn.net/qq_38380025/article/details/102968559
对微服务网关的理解
spring官网地址:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/
pom.xml 核心依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
SpringCloud Gateway
架构图(这个红色框的gateway是统一网关的统称)
微服务架构中,网关存在什么位置?
从架构图可以看出,所有的微服务并不是直接暴露出来的,而是通过网关统一分配和管理。
为什么需要使用spring-cloud-gateway
spring-cloud-gateway特性
spring-cloud-gateway和zuul区别在哪里
zuul模型(1.X)
webflux
springcloud gateway概念
- Route 路由
- predicate 断言
- filter 过滤
- 总体
上图中是核心的流程图,最主要的就是Route、Predicates 和 Filters 作用于特定路由。
1)Route:**路由是网关的基本构件**。它由ID、目标URI、谓词集合和过滤器集合定义。如果聚合谓词为真,则匹配路由。
2)Predicate:**参照Java8的新特性Predicate**。这允许开发人员匹配HTTP请求中的任何内容,比如头或参数。
3)Filter:可以在发送下游请求之前或之后修改请求和响应。
gateway工作流程
整体核心和逻辑其实就是:路由转发和过滤器链的执行。目的就是通过网关处理后,能够调用到最终的微服务提供者;
Demo搭建--网关配置
- 配置pom.xml依赖
<?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>spring-cloud-gateway</artifactId>
<groupId>com.wolf.boy</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-gateway-spring</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--额外引入网关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
</project>
注意:
不需要引入spring-boot-starter-web依赖。不然启动要报错,因为压根不需要。
- 配置yml配置文件
基本的配置
server:
port: 6666
spring:
application:
name: spring-cloud-gateway-spring
#Eureka服务提供者配置
eureka:
client:
#false表示不向注册中心注册自己(你自己就是一个eureka服务,没必要把自己注册进去了)
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
#这个主要结合discoveryClient使用
fetch-registry: true
service-url:
#单机版
defaultZone: http://localhost:9999/eureka
增加gateway的配置【路由映射】
映射配置
网关映射配置有两种
(1)基于yml,配置文件的
server:
port: 9438
spring:
application:
name: spring-cloud-gateway-spring
cloud:
gateway:
routes:
#路由的ID,没有固定规则,但是要求唯一,一般建议配合服务名
- id: provider_01_routh
uri: http://localhost:8881 #匹配后提供服务的路由地址(相当于前缀)
predicates:
- Path=/user/get/** #断言,路径相配的进行路由;也就是你请求的地址是这个,我匹配上了就用他
#- Before=2018-12-25T14:33:47.789+08:00 路由规则会在东8区的2018-12-25 14:33:47前,将请求都转跳到google。
#- After=2018-12-25T14:33:47.789+08:00 路由规则会在东8区的2018-12-25 14:33:47后,将请求都转跳到google
#- Between=2018-12-25T14:33:47.789+08:00, 2018-12-26T14:33:47.789+08:00
#- Cookie=cookiename, cookievalue 路由匹配请求存在cookie名为cookiename,cookie内容匹配cookievalue的,将请求转发到google。
#- Header=X-Request-Id, \d+ 路由匹配存在名为X-Request-Id,内容为数字的header的请求,将请求转发到google。
#- Host=**.somehost.org,**.anotherhost.org 路由会匹配Host诸如:www.somehost.org 或 beta.somehost.org或www.anotherhost.org等请求。
#- Method=GET 路由会匹配到所有GET方法的请求。
#- Path=/foo/{segment},/bar/{segment} 上面路由可以匹配诸如:/foo/1 或 /foo/bar 或 /bar/baz等 其中的segment变量可以通过下面方式获取
#- Query=foo, ba. 路由会匹配所有包含foo,并且foo的内容为诸如:bar或baz等符合ba.正则规则的请求
#- RemoteAddr=192.168.1.1/24 上面路由就会匹配RemoteAddr诸如192.168.1.10等请求。
- id: provider_02_routh
uri: http://localhost:8881
predicates:
- Path=/user/gateway/** #断言,路径相配的进行路由;也就是你请求的地址是这个,我匹配上了就用他
#Eureka服务提供者配置
eureka:
client:
#false表示不向注册中心注册自己(你自己就是一个eureka服务,没必要把自己注册进去了)
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
#这个主要结合discoveryClient使用
fetch-registry: true
service-url:
#单机版
defaultZone: http://localhost:9999/eureka
#集群版
#defaultZone: http://eureka9999.server:9999/eureka,http://eureka9998.server:9998/eureka
(2)基于代码的
官方参考 https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/
@Configuration
public class GateWayConfig {
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
//得到一个routes对象(跟yml一样)
RouteLocatorBuilder.Builder routes = builder.routes();
//PredicateSpec return:AsyncBuilder
routes.route("provider_01_routh_java_config_02",ps->{
return ps.path("/guonei").uri("https://news.baidu.com/guonei");
}).build();
return routes.build();
}
}
- 编写业务类
- 主启动类配置
@SpringBootApplication
//开启服务提供者(注册到Eureka中)
@EnableEurekaClient
public class RunClientGateWayMain {
public static void main(String[] args) {
SpringApplication.run(RunClientMain.class,args);
}
}
- 查看结果
正常情况下,如果知道服务提供者的IP地址+端口,也是可以正常访问的
http://localhost:8881/user/get
但是现在有了网关,请求先通过网关
http://localhost:9438/user/get
配置动态路由(基于服务名称的)
需要准备一个服务注册中心,然后二个服务提供者;
一个服务名称,下面有2个服务实例;
yml调整部分
spring:
cloud:
gateway:
#【新增参数】
discovery:
locator:
enabled: true #开启通过从服务注册中心动态创建路由功能,利用微服务进行路由
修改部分
#http://localhost:8881 #匹配后提供服务的路由地址(相当于前缀)
uri: lb://SPRING-CLOUD-EUREKA-PROVIDER-SERVER-01
完整的yml配置
server:
port: 9438
spring:
application:
name: spring-cloud-gateway-spring
cloud:
gateway:
#【新增参数】
discovery:
locator:
enabled: true #开启通过从服务注册中心动态创建路由功能,利用微服务进行路由
routes:
#路由的ID,没有固定规则,但是要求唯一,一般建议配合服务名
- id: provider_01_routh
uri: http://localhost:8881 #匹配后提供服务的路由地址(相当于前缀)
predicates:
- Path=/user/get/** #断言,路径相配的进行路由;也就是你请求的地址是这个,我匹配上
#http://localhost:8881 #匹配后提供服务的路由地址(相当于前缀)
//【lb】不要瞎写,后面就是服务名称
uri: lb://SPRING-CLOUD-EUREKA-PROVIDER-SERVER-01
predicates:
- Path=/user/gateway/** #断言,路径相配的进行路由;也就是你请求的地址是这个,我匹配上了就用他
#Eureka服务提供者配置
eureka:
client:
#false表示不向注册中心注册自己(你自己就是一个eureka服务,没必要把自己注册进去了)
register-with-eureka: false
#false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
#这个主要结合discoveryClient使用
fetch-registry: true
service-url:
#单机版
defaultZone: http://localhost:9999/eureka
#集群版
#defaultZone: http://eureka9999.server:9999/eureka,http://eureka9998.server:9998/eureka
启动后访问效果:
{"code":0,"msg":null,"result":"从服务端口:8882获取用户信息!gateway"}
{"code":0,"msg":null,"result":"从服务端口:8881获取用户信息!gateway"}
就能看见服务,在8881和8882之间进行切换;【实现了客户端基于网关服务的负载均衡】
Predicate 断言
也就是说,我们开始Yml配置里面开始说的
日期获取方式:
ZonedDateTime zonedDateTime = ZonedDateTime.now();
System.out.println(zonedDateTime.toString());
//控制台输出
2021-05-10T15:06:23.308+08:00[Asia/Shanghai]
对这些的支持。
上面这些配置哪里看的?官网啊 https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories
源代码查看实现类
Filter 过滤器
请求前和请求后,
种类有单一的和全局的两种;
单一的
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories
全局的
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#global-filters
自定义filter
参考:
https://blog.csdn.net/m0_37989980/article/details/105847031