1.gateWay
官方网站
Spring Cloud Gateway 使用的Webflux中的reactor-netty响应式编程组件,底层使用了Netty通讯框架
Webflux是spring5推出的异步非阻塞框架不同于springMvc
1.1 GateWay功能
- 反向代理
- 鉴权
- 流量控制
- 熔断
- 日志监控
1.2 三大核心
- 路由
路由是构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配该路由
- 断言
参考的是java8的java.util.function.Predicate开发人员可以匹配HTTP请求中的所有内容(例如请求头或请求参数),如果请求与断言相匹配则进行路由
- 过滤
指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修改。
1.3工作流程
路由转发+执行过滤器链
1.4案例演示
新建cloud-gateway-gateway9527模块
依赖
<!--新增gateway-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
配置文件
server:
port: 9527
spring:
application:
name: cloud-gateway
cloud:
gateway:
routes:
- id: payment_routh2 #id 不唯一即可
uri: http://localhost:8002 #匹配后提供服务的路由地址
predicates:
- Path=/payment/get/** #断言,路径相匹配的进行路由
- id: payment_routh
uri: http://localhost:8002 #匹配后提供服务的路由地址
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
#开启服务注册
eureka:
client:
service-url:
register-with-eureka: true
fetch-registry: true
defaultZone: http://localhost:7001/eureka
instance:
hostname: cloud-gateway-service
主要关注geteway下的内容 就体现了gateway的三大核心的 断言和路由
启动 7001 7002 8002 9527端口(案例沿用上一个博客的内容异步了解详细)
测试
predicates:
-path: 断言 (**表示通配)
uri:路由设置
1.5 负载均衡改造
默认情况下Gateway会根据注册中心的服务列表,以注册中心上微服务名为路径创建动态路由进行转发,从而实现动态路由的功能
因为我们做服务一般不可能一个服务只有一台机器,所以我们的路由地址不会写死,就会运用到Eureka注册的服务名称进行路由。因为我们的项目已经注册到Eureka地址。
需要注意的是uri的协议为lb,表示启用Gateway的负载均衡功能。
测试
1.6 Predicate的使用
因此我们已经是用了一个Path标记
其他参数我们可以参考官方网站的解释
获取时间格式的方式
System.out.println(ZonedDateTime.now());
测试
- id: payment_routh
# uri: http://localhost:8002 #匹配后提供服务的路由地址
uri: lb://CLOUD-PAYMENT-SERVICE #服务中心的服务名称 通过转发实现负载均衡高可用
predicates:
- Path=/payment/lb/** #断言,路径相匹配的进行路由
# - Between=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] , 2020-03-08T10:59:34.102+08:00[Asia/Shanghai] #在这个时间生效
# - Before=2020-03-08T10:59:34.102+08:00[Asia/Shanghai] #访问在这个时间之前才可以生效
# - Cookie=name,dfp # 设置访问请求需要带的cookie
# - Header=X-Request-Id, \d+ #请求头中要有X-Request-Id属性并且值为整数的正则表达式
# - Host=**.atguigu.com # 设置请求的uri地址 来自.atguigu.com
# - Method=GET #请求方式GET
# - After=2023-03-08T10:59:34.102+08:00[Asia/Shanghai] #访问的时间在这个时间之后才可以生效 【亚洲/上海时区】
1.7 filter过滤器
- 介绍
这样可以做到约束用户浏览服务器的行为,并且不需要实际的改变真实服务模块的代码,只需要在网关模块定义即可。
过滤器有2种方式
- 配置文件配置
在
cloud: gateway: routes:
下的filter进行配置
-
自定义实现类配置
新建一个类用作过滤配置GlobalFilterConfig
实现2 个接口 GlobalFilter ,Ordered
我们设置一个场景的意思就是请求头必须带有username不能为空
@Configuration
@Slf4j
public class GlobalFilterConfig implements GlobalFilter, Ordered {
@Override
public int getOrder() {
return 0;
}
/**
*
* @param exchange 类似于网络请求参数 httpreqeuest
* @param chain
*
*/
@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);
}
}
这样我们在9527端口访问进行转发的时候必须带有username
必须是username而且不为空
2.config分布式配置中心
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
随着分布式微服务的业务不断增加,模块划分越来越小,每个服务都有自己的 yml配置文件(properties)。如果每一次产品的更新迭代会需要我们逐步修改这些配置文件非常麻烦。
详细请阅读官网
2.1介绍
ABC 就是我们传统的分布式微服务,我们的Config就为我们提供了这样一种方案我们可以把所有配置统一的部分例如 数据库连接配置 服务注册中心的配置全部交给Configserver进行管理。实现修改一处ConfigServer、ABC处处修改。
这样就实现了再github上进行修改代码 然后由configService进行本地读取,子项目从configservice读取配置文件信息
- 作用
2.2案例演示
首先我们把yml的配置文件放到github上这里不做过多演示可以参考我的git使用博客进行操作
这里值得注意的是这些配置文件一定要符合我们的spring yml配置格式的规范
新建
cloud-config-center-3344作为我们的configService
cloud-config-client-3355作为我们的ABCservice这里我只演示一个其他集群通过Eureka可以实现
- cloud-config-center-3344
pom文件
配置文件
server:
port: 3344
spring:
application:
name: cloud-config-center
cloud:
config:
server:
git:
uri: #总配置github代码仓库地址
search-paths:
- config #存放的文件目录名称
label: master #分支
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
启动类
@SpringBootApplication
@EnableConfigServer
public class ConfigCenterMain3344 {
public static void main(String[] args) {
SpringApplication.run(ConfigCenterMain3344.class);
}
}
- cloud-config-client-3355
添加pom
配置文件bootstap.yml
server:
port: 3355
spring:
application:
name: config-client
cloud:
config:
label: master #分支名称
name: config #配置文件名称
profile: dev #后缀名
uri: http://localhost:3344 #你的springconfine 服务地址
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
特别说明
测试
我们的3355服务会根据配置文件定义的内容进行获取
- 问题
假如我们的的项目经理迭代了GitHub上的配置信息更新了最新的版本 将版本改为2
我们刷新测试
我们发现3344我们的服务configServic可以很好的进行更新
但是我的3355端口没有进行更新版本信息
这个时候我需要重启3355服务器让他加载配置文件的信息
但是每次重启很麻烦我们可以配置动态刷新
2.3Config客户端之动态刷新
添加到客户端
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
改造3355
在启动类上添加
@RefreshScope
在配置文件中配置 暴露暴露监控端口
management:
endpoint:
web:
exposure:
include: "*"
重启项目3355
修改github的内容
刷新页面
发现3344依旧可以自动更新,但是3355不可以,因为少了一步,我们需要告诉3355端口刷新内容但是不需要重启项目 cmd发送curl 的post命令刷新3355服务
curl -X POST "http://localhost:3355/actuator/refresh"
我们在修改github的内容后
发送命令刷新网页
3.Bus动态刷新全局广播
说说上面的springCloudConfig的方式我们得要一个个去子服务刷新让服务器去服务中心更新配置文件有没有一种可能,我们只需要通知服务中心让服务中心下发通知。进行全局的服务更新。
- Spring Cloud Bus配合Spring Cloud Config使用可以实现配置的动态刷新
- Bus支持两种消息代理:RabbitMQ和Kafka
架构图
我们这里用rabbitmq进行演示 需要学习安装rabbitmq的可以翻看我之前的博客
按照3355 新建子服务3366
3.1 案例
我们用2台机器演示
融合bus改造
3个机器都引入rabbitmq
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
3344
server:
port: 3344
spring:
rabbitmq:
host: 192.168.1.111
port: 5672
username: root
password: 123456
application:
name: cloud-config-center
cloud:
config:
server:
git:
uri: #总配置github代码仓库地址
search-paths:
- config #存放的文件目录名称
label: master #分支
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
management:
endpoints:
web:
exposure:
include: 'bus-refresh'
因为我们这次是刷新服务分发中心所以我们需要暴露服务中心的端口
3355
server:
port: 3355
spring:
application:
name: config-client
cloud:
config:
label: master
name: config
profile: dev
uri: http://localhost:3344
rabbitmq:
host: 192.168.1.111
port: 5672
username: root
password: 123456
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
management:
endpoints:
web:
exposure:
include: "*"
3366
server:
port: 3366
spring:
rabbitmq:
host: 192.168.1.111
port: 5672
username: root
password: 123456
application:
name: config-client
cloud:
config:
label: master
name: config
profile: dev
uri: http://localhost:3344
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka
management:
endpoints:
web:
exposure:
include: 'bus-refresh'
注意rabbitmq的地址是一致的,
测试 先后启动7001 3344 3355 3366
修改gitHub的配置内容为 6.6 !!!!按照config的思路进行测试(原先配置是6)
我们发送通知给3344
测试
一处通知处处更新
3.2单独通知某一个服务进行配置更新
我们在githun更新配置为6.7
因为我们在3355 3366都就进行了端口暴露
http://localhost:配置中心的端口号/actuator/bus-refresh/{destination}
现在我们只通知了3355
测试