Java微服务2

网关

把项目拆分成了多个部分,在进行交换的时候,如何验证安全性和yjwt这些呢?

如果每个都分发密钥的话,又会存在风险

网关:就是网络的关口,负责请求的路由、转发、身份校验。

image-20240317102541199

image-20240317102936133

快速入门

step1 创建新模块

image-20240317103308256

image-20240317104815549

step2 引入网关依赖

1
2
3
4
5
6
7
8
9
10
11
12
spring:  
cloud:
gateway:
routes:
- id: item # 路由规则id,自定义,唯一
uri: lb://item-service # 路由目标微服务,lb代表负载均衡
predicates: # 路由断言,判断请求是否符合规则,符合则路由到目标 -
Path=/items/** # 以请求路径做判断,以/items开头则符合
- id: xx
uri: lb://xx-service
predicates:
- Path=/xx/**

step3 编写启动类

image-20240317104833164

step4 配置路由规则

去resources 配置,在

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
server:
port:8080
前端请求发出,发给网关
spring:
application:
name:gateway
cloud:
nacos:
server-addr:192.168.150.101:8848//这个就是nacos的安装地址
gateway:
routes:
-id:item-service
路由的唯一标识,服务名字。应该是那个微服务的yaml写的
uri:lb://item-service(lb表示协议名字)
predicates:
-Path=/item/**,/search/**

-id: user-service
uri:lb://user-service
predicates:
-Path=/addresses/**,/users/**

image-20240317111829319

路由属性

网关路由对应的Java类型是RouteDefinition,其中常见的属性有:

  • id:路由唯一标示
  • uri:路由目标地址
  • predicates:路由断言,判断请求是否符合当前路由。
  • filters:路由过滤器,对请求或响应做特殊处理。

image-20240317142249280

image-20240317142344314

名称 说明 示例
After 是某个时间点后的请求 - After=2037-01-20T17:42:47.789-07:00[America/Denver]
Before 是某个时间点之前的请求 - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
Between 是某两个时间点之前的请求 - Between=2037-01-20T17:42:47.789-07:00[America/Denver], 2037-01-21T17:42:47.789-07:00[America/Denver]
Cookie 请求必须包含某些cookie - Cookie=chocolate, ch.p
Header 请求必须包含某些header - Header=X-Request-Id, \d+
Host 请求必须是访问某个host(域名) - Host=.somehost.org,.anotherhost.org
Method 请求方式必须是指定方式 - Method=GET,POST
Path 请求路径必须符合指定规则 - Path=/red/{segment},/blue/**
Query 请求参数必须包含指定参数 - Query=name, Jack或者- Query=name
RemoteAddr 请求者的ip必须是指定范围 - RemoteAddr=192.168.1.1/24
Weight 权重处理 - Weight=group1, 2
XForwarded Remote Addr 基于请求的来源IP做判断 - XForwardedRemoteAddr=192.168.1.1/24
AddRequestHeader 给当前请求添加一个请求头 AddrequestHeader=headerName,headerValue
RemoveRequestHeader 移除请求中的一个请求头 RemoveRequestHeader=headerName
AddResponseHeader 给响应结果中添加一个响应头 AddResponseHeader=headerName,headerValue
RemoveResponseHeader 从响应结果中移除有一个响应头 RemoveResponseHeader=headerName
RewritePath 请求路径重写 RewritePath=/red/?(?.*), /${segment}
StripPrefix 去除请求路径中的N段前缀 StripPrefix=1,则路径/a/b转发时只保留/b

网关登录校验

image-20240317152011836

image-20240317144533991

  • 如何在网关转发之前做登录校验?

  • 网关如何将用户信息传递给微服务?

  • 如何在微服务之间传递用户信息?

在最开始的pre部分就进行JWT校验,然后保存到请求头,因为网关和微服务的联系是http协议的,用保存到请求头是最方便的

自定义过滤器

原理:

网关过滤器有两种,分别是:

  • GatewayFilter:路由过滤器,作用于任意指定的路由;默认不生效,要配置到路由后生效。

  • GlobalFilter:全局过滤器,作用范围是所有路由;声明后自动生效。

两种过滤器的过滤方法签名完全一致:

image-20240317152329925

GlobalFilter步骤

step1自定义过滤器

image-20240317153953039

step2保证过滤器在nettyroutingfilter前执行

ctrl h

nettyroutingfilter 实现了globalfilter 、ordered

image-20240317154417252

image-20240317154550771

GatewayFilter开发比较麻烦

实现登录校验

image-20240317161207641

获取request

判断是否需要做登记

获取token

image-20240317161043431

校验并解析token

image-20240317161242789

传递用户信息

image-20240317161231553

放行

image-20240317161224211

image-20240317161216758

image-20240317175833120

实现登录校验

一、在网关的登录校验过滤器中,把获取到的用户写入请求头

需求:修改gateway模块中的登录校验拦截器,在校验成功后保存用户到下游请求的请求头中。
提示:要修改转发到微服务的请求,需要用到ServerWebExchange类提供的API,示例如下:

1
2
3
4
exchange.mutate() // mutate就是对下游请求做更改        
.request(builder -> builder.header("user-info", userInfo))
.build();

image-20240317203444339

OpenFeign传递用户

OpenFeign中提供了一个拦截器接口,所有由OpenFeign发起的请求都会先调用拦截器处理请求:

1
2
3
4
public interface RequestInterceptor {  /**   * Called for every request. Add data using methods on the supplied {@link RequestTemplate}.   */  
void apply(RequestTemplate template);
}

其中的RequestTemplate类中提供了一些方法可以让我们修改请求头:

image-20240317204509497

image-20240317205048040

image-20240317205446309

配置管理

微服务重复配置过多,维护成本高

业务配置经常变动,每次修改都要重启服务

网关路由配置写死,如果变更要重启网关

image-20240317205539196

监听配置的变更,变更了就推送给相应的微服务

实现配置的热更新

image-20240317205830739

配置共享

一.添加配置到Nacos

添加一些共享配置到Nacos中,包括:Jdbc、MybatisPlus、日志、Swagger、OpenFeign等配置

image-20240317210450372

添加一些共享配置到Nacos中,包括:Jdbc、MybatisPlus、日志、Swagger、OpenFeign等配置

image-20240317210509795

image-20240317210623417

二.拉取共享配置

基于NacosConfig拉取共享配置代替微服务的本地配置。

image-20240317211045349

①引入依赖

1
2
3
4
5
6
7
8
9
<!--nacos配置管理-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency> <!--读取bootstrap文件-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>

②新建bootstrap.yaml

image-20240317211200919

配置热更新

配置热更新:当修改配置文件中的配置时,微服务无需重启即可使配置生效。

前提条件:

①nacos中要有一个与微服务名有关的配置文件。

image-20240317212050543

image-20240317211842338

②微服务中要以特定方式读取需要热更新的配置属性

1
2
3
4
5
@Data
@ConfigurationProperties(prefix = "hm.cart")
public class CartProperties {
private int maxItems; }

1
2
3
4
5
6
@Data
@RefreshScope
public class CartProperties { @Value("${hm.cart.maxItems}")
private int maxItems;
}

image-20240317212657760

image-20240317212751287

image-20240317213403685

动态路由

实现动态路由需要将路由配置保存到Nacos,然后在网关监听Nacos中的路由配置,并实现配置热更新。然而网关路由并不是自定义业务配置属性,本身不具备热更新功能!参考:CompositeRouteDefinitionLocator

因此我们需要自己完成两件事情:

①监听Nacos配置变更的消息

②当配置变更时,将最新的路由信息更新到网关路由表

image-20240317214014466

image-20240317214021404

image-20240317214029557