1.nacos集群
1.1.创建数据库--nacos-mysql
1.2. 指定使用mysql作为数据存储
1.3. 配置集群文件
1.4. 停止nacos并复制三份
并修改端口号
5. 启动三个nacos
1.6. 搭建nginx代理上面三个nacos
1.7. 微服务注册到nacos集群上
2.gateway网关
2.1.使用gateway网关
(1)创建一个
gateway
微服务模块
(2)加入相关的依赖
<!--添加了该依赖就不要再使用spring-boot-stater-web依赖
因为gateway内置了服务器netty,而web的jar内置了tomcat
-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
(3)完成配置文件 application.yml:
server:
port: 7000
spring:
application:
name: springcloud-gateway
(4)创建
主启动类
@SpringBootApplication
public class GatewayApp {
public static void main(String[] args) {
SpringApplication.run(GatewayApp.class,args);
}
}
发现 : 路由配置时 uri 的地址还是一个固定的网络地址,如果后期微服务地址发送改变,也需要修改网关的配置。 不能完成负载均衡。解决 : gateway 也是一个微服务,它可以从注册中心拉取服务信息
2.2.让gateway网关从注册中心拉取服务型
1.引入依赖
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
2.修改配置文件指定注册中心地址
# 路由转发 List<RouteDefinition> routes
cloud:
gateway:
routes:
- id: qy-zsy-product
# 路由转发的真实地址 lb://微服务名称 默认采用ribbon负载均衡
uri: lb://qy-zsy-product
# predicates: 断言 当满足断言时,才会转发到真实的uri地址
predicates:
- Path=/product/**
- id: qy-zsy-order
# http://localhost:8092/order/buy/1/100
uri: lb://qy-zsy-order
predicates:
- Path=/order/**
# 指定注册中心的地址
nacos:
server-addr: localhost:81
发现: 有一个微服务需要配置一个路由,如果这时增加一个新的微服 务,则需要在配置文件中增加一个新的路由配置。能不能自动路由转发微服务呢! 可以
gateway
自动路由
修改配置文件
:
访问时
:
http://
网关的
ip:
网关的
port/
微服务名称
/
资源路径
2.3 介绍Gateway断言
在
gateway
中内置很多断言器,
SpringCloud Gateway包括许多内置的断言工厂,所有这些断言都与HTTP请求的不同属性匹配体如下:
基于**Datetime**类型的断言工厂
此类型的断言根据时间做判断,主要有三个:
AfterRoutePredicateFactory
: 接收一个日期参数,判断请求日期是否晚于指定日期
BeforeRoutePredicateFactory
: 接收一个日期参数,判断请求日期是否早于指定日期BetweenRoutePredicateFactory
: 接收两个日期参数,判断请求日期是否在指定时间段内
-After=2019-12-31T23:59:59.789+08:00[Asia/Shanghai]
基于远程地址的断言工厂**RemoteAddrRoutePredicateFactory**
接收一个
IP
地址段,判断请求主机地址是否在地址段中
-RemoteAddr=192.168.1.1/24
基于**Cookie**的断言工厂
CookieRoutePredicateFactory
:接收两个参数,
cookie
名字和一个正则表达式。判断请求cookie是否具有给定名称且值与正则表达式匹配。
-Cookie=chocolate, ch.
基于**Header**的断言工厂
HeaderRoutePredicateFactory
:接收两个参数,标题名称和正则表达式。 判断请求Header
是否
具有给定名称且值与正则表达式匹配。
key value
-Header=X-Request-Id, \d+
基于**Host**的断言工厂
HostRoutePredicateFactory
:接收一个参数,主机名模式。判断请求的Host
是否满足匹配规则。
-Host=**.testhost.org
基于**Method**请求方法的断言工厂
MethodRoutePredicateFactory
:接收一个参数,判断请求类型是否跟指定的类型匹配。
-Method=GET
基于**Path**请求路径的断言工厂
PathRoutePredicateFactory
:接收一个参数,判断请求的
URI
部分是否满足路径规则。
-Path=/foo/{segment}
基于Query请求参数的断言工厂
QueryRoutePredicateFactory
:接收两个参数,请求
param
和正则表达式, 判断请求参数是否具
有给定名称且值与正则表达式匹配。
-Query=baz, ba.
基于路由权重的断言工厂
WeightRoutePredicateFactory
:接收一个
[
组名
,
权重
],
然后对于同一个组内的路由按照权重转发
routes:
-id: weight_route1 uri: host1 predicates:
-Path=/product/**
-Weight=group3, 1
-id: weight_route2 uri: host2 predicates:
-Path=/product/**
-Weight= group3, 9
如果上面内置的断言不能满足需求:可以自定义断言。
注意
:
名称必须为
XXXRoutePredicateFactory
并且继承AbstractRoutePredicateFactory
使用时:
xxx=
2.4.过滤器
全局过滤器
作用
:
认证校验 黑白名单
敏感词
1.引入fastjson依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
2.创建Anon实体类
@Component
@ConfigurationProperties(prefix = "anon")
public class Anon {
private List<String> url;
public List<String> getUrl(){
return url;
}
public void setUrl(List<String> url){
this.url=url;
}
}
3.定义全局过滤器
@Component
public class LoginFilter implements GlobalFilter, Ordered {
@Autowired
private Anon anon;
//过滤方法 过滤业务
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
ServerHttpResponse response = exchange.getResponse();
//获取请求
String path = request.getPath().toString();
//判断当前的请求路径是否为放行路径
if(anon.getUrl().contains(path)){
//放行
return chain.filter(exchange);
}
//判断是否携带token
String token = request.getHeaders().getFirst("token");
//redis
if(StringUtils.hasText(token)&&"admin".equals(token)){
//放行
return chain.filter(exchange);
}
//返回一个json数据
//设置状态码
response.setStatusCode(HttpStatus.UNAUTHORIZED);
//封装返回数据
Map<String,Object> map = new HashMap<>();
map.put("msg","未登录");
map.put("code",4000);
//json转换
byte[] bytes = JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8);
//调用bufferFactory方法,生成DataBuffer对象
DataBuffer buffer = response.bufferFactory().wrap(bytes);
//调用Mono中的just方法,返回给前端的json数据
return response.writeWith(Mono.just(buffer));
}
@Override
// 优先级 返回的值越小优先级越高
public int getOrder() {
return 0;
}
}