从0开始构建你的api网关--Spring Cloud Gateway网关实战及原理解析
API 网关
API 网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:
- 客户端会多次请求不同的微服务,增加了客户端的复杂性。
- 存在跨域请求,在一定场景下处理相对复杂。
- 认证复杂,每个服务都需要独立认证。
- 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施。
- 某些微服务可能使用了防火墙 / 浏览器不友好的协议,直接访问会有一定的困难。
以上这些问题可以借助 API 网关解决。API 网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 API 网关这一层。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 API 网关来做,这样既提高业务灵活性又不缺安全性,典型的架构图如图所示:
使用 API 网关后的优点如下:
- 易于监控。可以在网关收集监控数据并将其推送到外部系统进行分析。
- 易于认证。可以在网关上进行认证,然后再将请求转发到后端的微服务,而无须在每个微服务中进行认证。
- 减少了客户端与各个微服务之间的交互次数。
API 网关选型
业界的情况:
我前面的文章<Netflix网关zuul(1.x和2.x)全解析>已经介绍了zuul1 和zuul2,现在就尝试从实例入手介绍一下spring cloud gateway
首先我们一步步实现一个最简单的网关例子
步骤1:在http://start.spring.io网站上创建一个spring-cloud-gateway-example项目,依赖spring-cloud-gateway,如下图所示
此时生产了一个spring-cloud-gateway-example的空项目包,pom.xml文件如下
<?xml version="1.0" encoding="UTF-8"?> <projectxmlns="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"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.3.RELEASE</version><relativePath/> <!--lookup parent from repository--></parent><groupId>com.example</groupId><artifactId>spring-cloud-gateway-example</artifactId><version>0.0.1-SNAPSHOT</version><name>spring-cloud-gateway-example</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><spring-cloud.version>Greenwich.RELEASE</spring-cloud.version></properties><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build><repositories><repository><id>spring-milestones</id><name>Spring Milestones</name><url>https://repo.spring.io/milestone</url></repository></repositories></project>
2.创建一个Route实例的配置类GatewayRoutes
packagecom.example.springcloudgatewayexample;importorg.springframework.cloud.gateway.route.RouteLocator;importorg.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration; @Configurationpublic classGatewayRoutes {@BeanpublicRouteLocator routeLocator(RouteLocatorBuilder builder) {returnbuilder.routes().route(r->r.path("/java/**").filters(f-> f.stripPrefix(1)).uri("http://localhost:8090/helloWorld")).build();} }
当然,也可以不适用配置类,使用配置文件,如下图所示
spring:cloud:gateway:routes: - predicates:- Path=/java/**filters:- StripPrefix=1uri: "http://localhost:8090/helloWorld"
不过,为了调试方便,我们使用配置类方式。
此时项目已经完成,足够简单吧。
3.启动此项目
>>因api网关需要转发到一个服务上,本文为http://localhost:8090/helloWorld,那需要先启动我上文<spring boot整合spring5-webflux从0开始的实战及源码解析>,你也可以创建一个普通的web项目,启动端口设置为8090,然后启动。
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.3.RELEASE)2019-02-21 09:29:07.450 INFO 11704 --- [ main] c.e.demo.Spring5WebfluxApplication : Starting Spring5WebfluxApplication on DESKTOP-405G2C8 with PID 11704 (E:\workspaceForCloud\spring5-webflux\target\classes started by dell in E:\workspaceForCloud\spring5-webflux) 2019-02-21 09:29:07.455 INFO 11704 --- [ main] c.e.demo.Spring5WebfluxApplication : No active profile set, falling back to default profiles: default 2019-02-21 09:29:09.409 INFO 11704 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8090 2019-02-21 09:29:09.413 INFO 11704 --- [ main] c.e.demo.Spring5WebfluxApplication : Started Spring5WebfluxApplication in 2.304 seconds (JVM running for 7.311)
>>以spring boot方式启动spring-cloud-gateway-example项目,日志如下
2019-02-21 10:34:33.435 INFO 8580 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$1e059320] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). ____ _ __ _ _/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \\\/ ___)| |_)| | | | | || (_| | ) ) ) )' |____| .__|_| |_|_| |_\__, | / / / /=========|_|==============|___/=/_/_/_/:: Spring Boot :: (v2.1.3.RELEASE)2019-02-21 10:34:33.767 INFO 8580 --- [ main] e.s.SpringCloudGatewayExampleApplication : No active profile set, falling back to default profiles: default
2019-02-21 10:34:34.219 INFO 8580 --- [ main] o.s.cloud.context.scope.GenericScope : BeanFactory id=d98183ec-3e46-38ba-ba4c-e976a1017dce
2019-02-21 10:34:34.243 INFO 8580 --- [ main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration' of type [org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration$$EnhancerBySpringCGLIB$$1e059320] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2019-02-21 10:34:44.367 INFO 8580 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [After]
2019-02-21 10:34:44.367 INFO 8580 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Before]
2019-02-21 10:34:44.367 INFO 8580 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Between]
2019-02-21 10:34:44.367 INFO 8580 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Cookie]
2019-02-21 10:34:44.367 INFO 8580 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Header]
2019-02-21 10:34:44.368 INFO 8580 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Host]
2019-02-21 10:34:44.368 INFO 8580 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Method]
2019-02-21 10:34:44.368 INFO 8580 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Path]
2019-02-21 10:34:44.368 INFO 8580 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Query]
2019-02-21 10:34:44.368 INFO 8580 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [ReadBodyPredicateFactory]
2019-02-21 10:34:44.368 INFO 8580 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [RemoteAddr]
2019-02-21 10:34:44.368 INFO 8580 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [Weight]
2019-02-21 10:34:44.368 INFO 8580 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : Loaded RoutePredicateFactory [CloudFoundryRouteService]
2019-02-21 10:34:44.920 INFO 8580 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2019-02-21 10:34:44.923 INFO 8580 --- [ main] e.s.SpringCloudGatewayExampleApplication : Started SpringCloudGatewayExampleApplication in 12.329 seconds (JVM running for 13.126)
4.测试,浏览器访问http://localhost:8080/java/helloWorld
返回hello world !
5.从上面的代码和配置及实例中,我们可以看出spring cloud gateway处理request请求的流程如下所示:
即在最前端,启动一个netty server(默认端口为8080)接受请求,然后通过Routes(每个Route由Predicate(等同于HandlerMapping)和Filter(等同于HandlerAdapter))处理后通过Netty Client发给响应的微服务。
那么在gateway本身最重要的应该是Route(Netty Server和Client已经封装好了),它由RouteLocatorBuilder构建,内部包含Predicate和Filter,
private Route(String id, URI uri, int order, AsyncPredicate<ServerWebExchange> predicate, List<GatewayFilter>gatewayFilters) {this.id =id;this.uri =uri;this.order =order;this.predicate =predicate;this.gatewayFilters =gatewayFilters;}
那么我们就来探讨一下这两个组件吧
5.1.Predicate
Predicte由PredicateSpec来构建,主要实现有:
以path为例
/*** A predicate that checks if the path of the request matches the given pattern*@parampatterns the pattern to check the path against.* The pattern is a {@linkorg.springframework.util.PathMatcher} pattern*@returna {@linkBooleanSpec} to be used to add logical operators*/publicBooleanSpec path(String... patterns) {return asyncPredicate(getBean(PathRoutePredicateFactory.class).applyAsync(c->c.setPatterns(Arrays.asList(patterns))));}
PathRoutePredicateFactory中执行
@Overridepublic Predicate<ServerWebExchange>apply(Config config) {final ArrayList<PathPattern> pathPatterns = new ArrayList<>();synchronized (this.pathPatternParser) {pathPatternParser.setMatchOptionalTrailingSeparator(config.isMatchOptionalTrailingSeparator());config.getPatterns().forEach(pattern->{PathPattern pathPattern= this.pathPatternParser.parse(pattern);pathPatterns.add(pathPattern);});}return exchange ->{PathContainer path=parsePath(exchange.getRequest().getURI().getPath());Optional<PathPattern> optionalPathPattern =pathPatterns.stream().filter(pattern->pattern.matches(path)).findFirst();if(optionalPathPattern.isPresent()) {PathPattern pathPattern=optionalPathPattern.get();traceMatch("Pattern", pathPattern.getPatternString(), path, true);PathMatchInfo pathMatchInfo=pathPattern.matchAndExtract(path);putUriTemplateVariables(exchange, pathMatchInfo.getUriVariables());return true;}else{traceMatch("Pattern", config.getPatterns(), path, false);return false;}};}
5.2.Filter
Filter分两种,一种GatewayFilter,一种GlobalFilter
5.2.1 GatewayFilter
GatewayFilter由GatewayFilterSpec构建,GatewayFilter的构建器
5.2.2 GlobalFilter
5.3 GlobalFilter和GatewayFilter的联系
FilteringWebHandler.GatewayFilterAdapter代理了GlobalFilter
6.总结
本文从一个spring-cloud-gateway实例入手,深入浅出的介绍了spring-cloud-gateway的组件,并从源码角度给出了实现的原理。
spring-cloud-gateway在最前端,启动一个netty server(默认端口为8080)接受请求,然后通过Routes(每个Route由Predicate(等同于HandlerMapping)和Filter(等同于HandlerAdapter))处理后通过Netty Client发给响应的微服务。
Predicate和Filter的各个实现定义了spring-cloud-gateway拥有的功能。
参考资料:
【1】https://www.infoq.cn/article/comparing-api-gateway-performances
【2】https://dzone.com/articles/spring-cloud-gateway-configuring-a-simple-route
转载于:https://www.cnblogs.com/davidwang456/p/10411451.html
从0开始构建你的api网关--Spring Cloud Gateway网关实战及原理解析相关推荐
- spring cloud gateway 网关_微服务网关Spring Cloud Gateway全搞定
一.微服务网关Spring Cloud Gateway 1.1 导引 文中内容包含:微服务网关限流10万QPS.跨域.过滤器.令牌桶算法. 在构建微服务系统中,必不可少的技术就是网关了,从早期的Zuu ...
- 【硬核】Spring Cloud Gateway(网关)
概念 Gateway是基于异步非阻塞模型上进行开发的,有springcloud团队开发.用来代替Zuul. 近几个月收集了收集了N份精校过的PDF版的Java八股文大全,涉及Java后端的方方面面,分 ...
- 微服务网关spring cloud gateway入门详解
1.API网关 API 网关是一个处于应用程序或服务( REST API 接口服务)之前的系统,用来管理授权.访问控制和流量限制等,这样 REST API 接口服务就被 API 网关保护起来,对所有的 ...
- Spring Cloud(10)——新一代网关Spring Cloud Gateway
文章目录 Spring Cloud(10)--新一代网关Spring Cloud Gateway 1.背景知识--API网关 2.Spring Cloud Gateway 详细概述 3.Spring ...
- Spring Cloud学习笔记—网关Spring Cloud Gateway官网教程实操练习
Spring Cloud学习笔记-网关Spring Cloud Gateway官网教程实操练习 1.Spring Cloud Gateway介绍 2.在Spring Tool Suite4或者IDEA ...
- Spring Cloud Gateway网关
Spring Cloud Gateway网关 1. 简介 Spring Cloud Gateway是Spring官网基于Spring 5.0. Spring Boot 2.0.Project Reac ...
- Spring Cloud Gateway网关实现短网址生成、解析、转发
Spring Cloud Gateway网关实现短网址生成.解析.转发 1.概述 2.基础实现 3.路由处理HandlerFunction 4.配置路由 5.测试 1.概述 在一些生成二维码等场景中, ...
- 客快物流大数据项目(一百一十七):网关 Spring Cloud Gateway
文章目录 网关 Spring Cloud Gateway 一.简介 1.功能特性
- Spring Cloud Gateway — 网关基本功能API暴露
API网关 API网关是一种设计模式,一种在微服务体系下的经典构件.要了解最新API网关模式可以参考敖小剑写的<Service Mesh和Api Gateway关系深度探讨> 早期SOA阶 ...
最新文章
- 网络安全系列之五十 对Web主目录进行备份
- 从零开始开发JVM语言(十一)Lambda
- jackson 反序列化string_Java 中使用Jackson反序列化
- Launcher(待完善...)
- MySQL调优(八):查缺补漏(mysql的锁机制,读写分离,执行计划详解,主从复制原理)
- CSS: hover选择器的使用
- [react] 使用PropTypes和Flow有什么区别?
- LintCode 1816. 使结果不超过阈值的最小除数(二分查找)
- 释放囚犯(洛谷-P1622)
- 移动端的开发-视口-适配
- ansible基本模块-shell
- sql join on和不用join区别_图解 SQL 各种 JOIN,太有用了!
- Android TableLayout 表格布局
- 16. jQuery - 获取并设置 CSS 类
- C#获取dynamic(动态)或非动态实体的属性值
- 六、Linux企业级YUM软件管理
- 设计模式 ( 十二 ) 静态代理模式
- 简单循迹小车实验心得_简单循迹小车的制作
- pr基本剪辑操作/视频导出操作
- 微信聊天小程序——(五、添加好友)
热门文章
- python用numpy和pil处理图像成灰度图_「火炉炼AI」机器学习047-图像的直方图均衡化操作...
- TortoiseGit git push提示fatal: HttpRequestException encountered remote: Invalid username or password.
- spring boot第八讲
- laravel php配置,PHP Laravel框架路由配置及设置技巧全解
- 本科985末端去哪学计算机好,4所“985高校”,录取分较低,常被拿来捡漏!
- python rsa_python rsa加解密
- react ui框架_顶级React组件库推荐
- openssl 加密解密 指令_OpenSSL未来架构设计,3.0初步实现
- 第六代微型计算机是,AMD Carrizo第六代A系列处理器技术解析
- 验证码的产生 python