SpringCloudAlibaba-服务⽹关Gateway
⼀:⽹关简介
在微服务架构中,⼀个系统会被拆分为很多个微服务。那么作为客户端要如何去调⽤这么多的微服务呢?如果没有⽹关的存在,我们只能在客户端记录每个微服务的地址,然后分别去调⽤。这样的话会产⽣很多问题,例如:
客户端多次请求不同的微服务,增加客户端代码或配置编写的复杂性
认证复杂,每个微服务都有独⽴认证
存在跨域请求,在⼀定场景下处理相对复杂
为解决上⾯的问题所以引⼊了⽹关的概念:所谓的API⽹关,就是指系统的统⼀⼊⼝,它封装了应⽤程序的内部结构,为客户端提供统⼀服务,⼀些与业务本⾝功能⽆关的公共逻辑可以在这⾥实现,诸如认证、鉴权、监控、路由转发等。
⽐较流⾏的⽹关对⽐
Nginx+lua
使⽤nginx的反向代理和负载均衡可实现对api服务器的负载均衡及⾼可⽤lua是⼀种脚本语⾔,可以来编写⼀些简单的逻辑, nginx⽀持lua 脚本
Kong
基于Nginx+Lua开发,性能⾼,稳定,有多个可⽤的插件(限流、鉴权等等)可以开箱即⽤。问题:只⽀持Http协议;⼆次开发,⾃由扩展困难;提供管理API,缺乏更易⽤的管控、配置⽅式。
Zuul
Netflix开源的⽹关,功能丰富,使⽤JAVA开发,易于⼆次开发问题:缺乏管控,⽆法动态配置;依赖组件较多;处理Http请求依赖的是Web容器,性能不如Nginx
Spring Cloud Gateway
Spring公司为了替换Zuul⽽开发的⽹关服务,将在下⾯具体介绍。
⼆:Gateway简介
Spring Cloud Gateway是Spring公司基于Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发
的⽹关,它旨在为微服务架构提供⼀种简单有效的统⼀的 API 路由管理⽅式。它的⽬标是替代Netflix Zuul,其不仅提供统⼀的路由⽅式,并且基于 Filter 链的⽅式提供了⽹关基本的功能,例如:安全,监控和限流。
优点:
1. 性能强劲:是第⼀代⽹关Zuul的1.6倍
2. 功能强⼤:内置了很多实⽤的功能,例如转发、监控、限流等
3. 设计优雅,容易扩展
缺点:
1. 其实现依赖Netty与WebFlux,不是传统的Servlet编程模型,学习成本⾼
2. 不能将其部署在Tomcat、Jetty等Servlet容器⾥,只能打成jar包执⾏
3. 需要Spring Boot 2.0及以上的版本,才⽀持
三:Gateway核⼼架构
3.1:基本概念
路由(Route) 是 gateway 中最基本的组件之⼀,表⽰⼀个具体的路由信息载体。主要定义了下⾯的⼏个信息:
id:路由标识、区别于其他route
uri:路由指向的⽬的地uri,即客户端请求最终被转发到的微服务
order:⽤于多个route之间的排序,数值越⼩排序越靠前,匹配优先级越⾼
predicate:断⾔的作⽤是进⾏条件判断,只有断⾔都返回真,才会真正的执⾏路由
filter:过滤器⽤于修改请求和响应信息
3.2:执⾏流程
nginx和网关怎么配合使用1. Gateway Client向Gateway Server发送请求
2. 请求⾸先会被HttpWebHandlerAdapter进⾏提取组装成⽹关上下⽂
3. 然后⽹关的上下⽂会传递到DispatcherHandler,它负责将请求分发给RoutePredicateHandlerMapping
4. RoutePredicateHandlerMapping负责路由查,并根据路由断⾔判断路由是否可⽤
5. 如果过断⾔成功,由FilteringWebHandler创建过滤器链并调⽤
6. 请求会⼀次经过PreFilter--微服务--PostFilter的⽅法,最终返回响应
四:Gateway快速⼊门
4.1:创建⼀个api-gateway模块,导⼊相关依赖
<project xmlns="/POM/4.0.0"
xmlns:xsi="/2001/XMLSchema-instance"
xsi:schemaLocation="/POM/4.0.0 /xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud-alibaba</artifactId>
<groupId>com.chenpt</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>api-gateway</artifactId>
<dependencies>
<!--nacos客户端-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--gateway⽹关-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
</dependencies>
</project>
完整版l
4.2:创建启动类
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {
public static void main(String[] args){
SpringApplication.run(GatewayApplication.class, args);
}
}
GatewayApplication
4.3:添加配置⽂件
server:
port: 7000
spring:
application:
name: api-gateway
cloud:
nacos:
discovery:
server-addr: localhost:8848
gateway:
routes: # 路由数组[路由就是指定当请求满⾜什么条件的时候转到哪个微服务]
- id: product_route # 当前路由的标识, 要求唯⼀
uri: lb://service-product # lb指的是从nacos中按照名称获取微服务,并遵循负载均衡策略
predicates: # 断⾔(就是路由转发要满⾜的条件)
- Path=/shop-pro/** # 当请求路径满⾜Path指定的规则时,才进⾏路由转发
filters: # 过滤器,请求在传递过程中可以通过过滤器对其进⾏⼀定的修改
- StripPrefix=1 # 转发之前去掉1层路径
- id: order_route
uri: lb://service-order
predicates:
- Path=/shop-order/**
filters:
- StripPrefix=1
4.4:测试
五:⽹关限流
采⽤前⾯学过的Sentinel组件来实现⽹关的限流
5.1:导⼊依赖
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
5.2:编写配置类
基于Sentinel 的Gateway限流是通过其提供的Filter来完成的,使⽤时只需注⼊对应的SentinelGatewayFilter实例以及SentinelGatewayBlockExceptionHandler 实例即可。
@Configuration
public class GatewayConfig {
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public GatewayConfig(List<ViewResolver> viewResolvers, ServerCodecConfigurer serverCodecConfigurer) {
this.viewResolvers = viewResolvers;
this.serverCodecConfigurer = serverCodecConfigurer;
}
// 初始化⼀个限流的过滤器
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public GlobalFilter sentinelGatewayFilter() {
return new SentinelGatewayFilter();
}
// 配置初始化的限流参数
@PostConstruct
public void initGatewayRules() {
// Set<GatewayFlowRule> rules = new HashSet<>();
// rules.add(
/
/ new GatewayFlowRule("product_route") //资源名称,对应路由id
// .setCount(1) // 限流阈值
// .setIntervalSec(1) // 统计时间窗⼝,单位是秒,默认是 1 秒
// );
// GatewayRuleManager.loadRules(rules);
Set<GatewayFlowRule> rules = new HashSet<>();
rules.add(new GatewayFlowRule("product_route").setCount(1).setIntervalSec(1));
rules.add(new GatewayFlowRule("order_route").setCount(1).setIntervalSec(1));
GatewayRuleManager.loadRules(rules);
}
// 配置限流的异常处理器
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
}
// ⾃定义限流异常页⾯
@PostConstruct
public void initBlockHandlers() {
BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
@Override
public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
Map map = new HashMap<>();
map.put("code", 0);
map.put("message", "接⼝被限流了");
return ServerResponse.status(HttpStatus.OK).
contentType(MediaType.APPLICATION_JSON_UTF8). body(BodyInserters.fromObject(map));
}
};
GatewayCallbackManager.setBlockHandler(blockRequestHandler); }
}
GatewayConfig
5.3:测试
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论