api网关作为反向代理,对外部系统提供统一的服务访问入口,对请求进行鉴权限流等访问控制处理,通过后将请求路由转发给后端服务。在高并发和潜在的高延迟场景下,api网关要实现高性能高吞吐量的一个基本要求是全链路异步,不要阻塞线程。spring cloud zuul网关采用同步阻塞模式不符合要求。
先前基于servlet,采用异步servlet filter + 异步servlet+servlet异步io+异步httpclient做过全链路异步http/rest api网关,要强调的是使用异步servlet后只是流程上异步,并不意味着io这块自动就是异步,还要使用servlet异步io才能真正达成网络io的高吞吐量。异步httpclient当时用的是基于netty的async-http-client库。
spring终于在版本5中提供反应式编程支持,比较完美地支持异步非阻塞编程,先前的spring系包括spring mvc大多是同步阻塞的编程模式,使用thread-per-request处理模型。即使在spring mvc controller方法上加@Async注解或返回DeferredResult、Callable类型的结果,其实仍只是把方法的同步调用封装成执行任务放到线程池的任务队列中,还是thread-per-request模型。靠线程池实现的伪异步,为何说它是伪异步,因为在出现高并发请求时,需要增大线程池的线程数(可能要几十个或几百个线程),由于仍是同步阻塞任务,加上线程调度开销,这种伪异步实际上不可能实现理想的高并发,这个问题根源是Java先前大多提供的是同步阻塞库或规范,也没有golang类似的官方支持的协程,例如还没有异步的JDBC api,不得已只能这样。不过这些都在改善提高中,例如openJDK中的Loom项目就计划实现协程功能,而阿里巴巴的Wisp协程技术已经在阿里生产环境中使用,这两个(Loom和Wisp)未来可能会合并成一个项目。异步JDBC在两年之内应该可以发布。真正的异步非阻塞任务处理,不需要过多的线程就能实现理想的高并发,线程数过多反而有副作用,通常线程数不大于cpu核数的两倍,一般就是cpu核数。
在node.js非阻塞异步编程和vertx的冲击下,spring5对反应式编程的支持可以说和先前走在前列的vertx并驾齐驱了,让spring粉丝们松了口气。spring5基于reactor3提供webflux模块来支持web反应式编程,反应式提倡异步非阻塞,背压这里就不说了。异步servlet是在原来的servlet同步模型上打补丁来实现的,和spring5全新设计的webflux不可同日而语。
基于webflux的网关主要组件是webfilter过滤器(webflux中的webfilter和servlet filter是两码事,虽然概念类似,但其底层缺省的运行时是基于netty,不是tomcat,虽然也可适配tomcat或jetty这些传统容器。webflux不用servlet那一套编程模型,servlet中的HttpServletRequest、HttpServletResponse这些类不能在webflux中使用),多个过滤器分别实现认证授权、限流、请求路由转发、正常响应回写(把后端服务的响应回写给调用网关的前端系统)等。如果调用后端服务时要做协议转换,例如前端请求是http(s),后端服务是rpc,那就要做协议转换,这块可以参考spring mvc和spring webflux的控制器方法参数解析器和返回值处理器,特殊情况下可以提供配置界面来设置两个协议数据之间的属性映射关系。协议转换组件最好能做成插件的形式。
异步io包括webflux适用的场景是高并发高延迟的场景,在并发度小或后端服务延迟(后端服务耗时)小于10ms左右的情况下,采用异步io因为线程的调度开销,性能和吞吐量反而不如阻塞io。
参考架构
这里的前端并不是通常说的ui前端,而是指角色,这些系统需要接入网关来调用后端的服务,他们是服务消费者,在网关前面。
代码仓库
代码在github demo-spring-webflux-api-gateway仓库上,有两个分支:master和dev。
使用技术
反应式&异步非阻塞io:springboot2+spring reactor 3+spring5 webflux包括webclient、webfilter、controller。
这个是从生产项目中抽出基本的架子作为演示,跑起来是没问题的,使用maven构建。
服务路由
后端服务的url前缀(域名和http schema)是固定的,在application.properties文件中由backend.service.url.prefix属性来配置,例如backend.service.url.prefix=http://127.0.0.1:8080 。
假设前端应用(服务消费者)用如下url调用网关(网关端口为9988)
http://api.gateway.demo:9988/orders/1234
如果请求过滤通过,网关最后会将请求路由转发到http://127.0.0.1:8080/orders/1234,这个url提供订单服务。
在实际的生产环境中,一般是后端有多个服务,部署在多个不同的服务域名上,特别是采用微服务架构后,网关需要从服务注册中心获取后端服务的endpoint信息(如果后端服务是http,主要是url前缀部分,例如http schema(http、https)+服务域名或ip+端口),而不是这种演示情况下使用固定前缀的方式。如果以网关为中心,注册中心可以是网关的一个模块或子系统,也可是独立的系统。
在有多个后端服务域名的情况下,为了方便网关进行路由,可以在前端请求中携带路由提示信息。这个路由提示信息的粒度可大可小:可以是细粒度的服务名,它对应一个url模式+http方法(考虑restful风格),根据服务名可以映射到服务所在的endpoint;也可是粗粒度的服务名,这个粗粒度的服务名其实是一个应用名(app name)或逻辑域,这个应用上可有多个细粒度的服务,应用名再映射到真实的endpoint上。服务名可放在http请求头中或在url中靠前的位置,例如http://api.gateway.demo:9988/order-center/orders/1234 这个url中的order-center就是粗粒度的服务名(应用名),网关可根据这个服务名从注册中心找到对应的后端服务域名和http schema等url endpoint信息。
如果众多请求url模式+http方法不冲突,能确保网关根据请求信息(主要是请求url和http方法)找到对应的路由endpoint地址,也可以不加服务名。
相关类介绍
1)main class为com.demo.http.api.gateway.main.RestApiGateWayApplication。
在IDE中直接运行这个类即可跑起来,或mvn package打包,再java -jar运行jar包。
2)过滤器类位于com.demo.http.api.gateway.access.filter包中,已经有两个过滤器:RequestAuthFilter和RateLimitFilter,分别用于鉴权和限流。过滤器类上有Order注解,决定该过滤器在过滤器链中的调用先后顺序,order数值小的先调用。作为演示,鉴权只是看请求中有没有appKey的http头,限流是放过所有请求不进行限流。
3)控制器类:转发请求到后端服务是由com.demo.http.api.gateway.access.controller.ApiProxyController控制器来实现的,也可用过滤器来实现,只是生产项目当时写的顺手用控制器来做了,没改过来。对后端http服务的调用使用webflux模块提供的WebClient,它支持异步和同步两种调用方式。使用反应式编程,对http client不推荐使用spring先前的RestTemplate和AsyncRestTemplate。其他几个控制器用来生成异常情况下的响应数据发给前端,这些也可不需要,而是直接在过滤器中(过滤器验证未通过或后端服务网络异常)生成异常数据并发给前端,在代码中有直接的,也有转发到控制器的。
前端请求中除了要有appKey http头,大多还需要携带类似token头和请求数据签名,如何获取token和对token进行验证这里不介绍。
4)服务类:com.demo.http.api.gateway.service.AppInfoProvider 根据appKey来获取调用方的应用信息(应用密钥),演示情况下没有调用AppInfoProvider的方法,只是把AppInfoProvider实例注入到RequestAuthFilter类中。
5)过滤器父类
dev分支中的过滤器均继承父类com.demo.http.api.gateway.access.filter.base.AbstractGatewayWebFilter,这个类采用模板方法设计模式。
子类只要实现两个模板方法doFilter和doDenyResponse。doFilter实现过滤器的业务逻辑,有两种过滤结果:布尔值类型TRUE和FALSE(代码中其实是布尔类型的反应式版本Mono<Boolean>)。TRUE表示过滤通过(pass),请求控制流会转到过滤器链中的下个filter或controller; 如果是FALSE,未通过(deny),会调用doDenyResponse方法,在这个方法中一般是生成deny响应数据发给前端系统,结束该请求的处理。这两个方法在dev分支的过滤器中有实现,特别是RequestAuthFilter。
该类中还有个skipProcess方法,filter可调用这个方法指示后面的filter跳过对该请求的处理,也就是不执行doFilter。
6)服务层和dao层
com.demo.http.api.gateway.service.AppInfoProvider提供方法用来根据appKey(应用名)获取该应用的密钥等app信息,app信息使用了spring caffeine缓存。com.demo.http.api.gateway.dao.mapper.AppInfoMapper是app信息的dao类,使用myibatis。
7)工具类
com.demo.http.api.gateway.util.WebfluxForwardingUtil,提供forward方法来让filter在需要的时候forward请求到网关内部的其他目标url。controller中如何forward在先前博文中有介绍。
配置文件
application.properties内容如下:
#spring.profiles.active=dev
#网关服务端口
server.port=9988
#网关url前缀,目前没有使用
gateway.url.prefix=/api
#调用后端服务的超时时间,单位毫秒。生产项目应该是根据具体的服务取对应的超时配置
backend.service.timeout.inmillis=10000
#后端服务endpoint,生产项目通常应该从注册中心获取服务和它对应的endpoint关系
backend.service.url.prefix=http://127.0.0.1:8080
#数据库配置,作为演示项目,没有调用数据库,不需要配置下面的属性
datasource.mysql.jdbcUrl=jdbc:mysql://127.0.0.1:3308/gateway?useUnicode=true&characterEncoding=utf-8
datasource.mysql.user=
datasource.mysql.password=
datasource.mysql.driverClass=com.mysql.jdbc.Driver
datasource.mysql.driverClass.type=com.mchange.v2.c3p0.ComboPooledDataSource
datasource.mysql.testWhileIdle = true
datasource.mysql.preferredTestQuery=SELECT 1
datasource.mysql.testConnectionOnCheckin = true
datasource.mysql.idleConnectionTestPeriod = 400
datasource.mysql.maxIdleTime = 500
后记
编写高性能api网关也可采用协程,当有阻塞时,阻塞在协程上而不是阻塞在线程上。和线程相比,协程是很轻量级的资源,在一个线程中可有几千个协程,协程的调度在用户级,调度开销也比线程小得多,所以采用协程也能实现网络io或io密集型系统的高吞吐量。反应式的组合链式调用风格可极大地减轻回调地狱问题(callback hell),而协程提供同步风格的代码编写体验,同步风格符合开发人员的心智模型和习惯,提高了编码效率,同时同步风格完全消除了回调地狱,显著改善代码的可维护性。
webflux中的reactor netty反应式运行时包括webclient目前还不支持http2,今年下半年应该就可以了。http2在一个http连接上能真正并发多个请求,这样在高并发情况下连接池中只要不多的连接资源,也避免了高并发时等待空闲连接的窘境或新建连接的时间。
相关推荐
Clivia 是一个强大的 API Gateway,它利用了Spring WebFlux框架的优势,为现代微服务架构提供了高度可扩展、高性能、高弹性和响应式的服务。API Gateway是系统架构中的一个重要组件,它作为前端应用与后端服务之间的...
这是一个基于SpringWebFlux和Netty的高性能,响应式API网关。 现在它仅支持HTTP协议转发,仅用于学习通信。 项目结构 Ship-admin:网关管理控制台,支持配置路由规则等。 船舶服务器:网关服务器,核心功能模块。 ...
总的来说,这个学生作业管理系统服务端项目融合了SpringCloud的微服务治理和Spring WebFlux的高性能特性,结合MongoDB和Node.js,构建了一个高效、稳定的分布式系统。这样的实践有助于开发者更好地理解和掌握微服务...
通过深入学习和实践"springwebflux-bootcamp-api-gateway"项目,开发者可以掌握如何利用Spring WebFlux构建高性能、高可用的API网关,并进一步提升在微服务架构中的技能。同时,该项目也是一个很好的起点,帮助我们...
设计和实现一个高性能的API网关 在本文中,我们将讨论如何设计和实现一个高性能的API网关。该网关将具备高吞吐量、可扩展性、负载均衡、灰度发布、接口鉴权等功能。 首先,我们需要选择合适的技术栈。网关是所有...
然而,随着Spring生态系统的发展,SpringCloud Gateway应运而生,它基于Spring Framework 5、Project Reactor和Spring WebFlux,提供了更高的性能和更现代的架构。SpringCloud Gateway提供了更灵活的路由规则定义,...
1. **Spring WebFlux**: Spring WebFlux是Spring Framework的一个模块,支持非阻塞和反应式编程模型,用于构建高性能的Web应用程序。它使用Reactor作为默认的反应式库,但也可以与RxJava等其他反应式库配合使用。 2...
8. **Spring Cloud**:对于微服务架构,介绍了Spring Cloud的相关组件,如Eureka(服务发现)、Zuul(API网关)、Hystrix(断路器)等,用于构建分布式系统。 9. **源码解读**:部分章节可能涉及Spring框架的源码...
Fizz Gateway是一个基于Java开发的微服务网关,能够实现热服务编排,自动授权选择,在线服务脚本编码,在线测试,高性能路由,API审核管理等目的,拥有强大的自定义插件系统可以自行扩展,并提供友好的图形化配置...
它基于Spring Framework和Spring WebFlux,提供了更强大、更灵活的路由功能,以及过滤器链的处理方式,性能也有所提升。 在前后端分离的架构中,前端通常使用现代化的JavaScript框架,如React、Vue.js或Angular。...
1.http/rest api网关:作为反向代理,对外部系统提供统一的服务访问入口,进行鉴权、授权、限流等...2.高性能:React式&异步非阻塞io,springboot2+spring5 webflux包括webclient、webfilter、controller 3.详细介绍见
这是一个基于Spring Framework 5,Spring Boot 2 和 Project Reactor 的高性能API网关。它提供了动态路由,服务熔断,负载均衡,以及针对微服务的细粒度控制等功能。通过自定义过滤器,我们可以实现复杂的业务逻辑,...
首先,Spring 5是Java开发者广泛使用的开源框架,它的主要改进包括对Java 8及更高版本的全面支持、反应式编程的支持(通过Spring Framework 5.0的WebFlux模块)、更好的类型安全的事件处理系统,以及对HTTP/2协议的...
Zuul是SpringCloud早期的API网关,而Spring Cloud Gateway则是新一代的网关,基于Spring Framework 5、Project Reactor和Spring WebFlux构建,提供了更强大的过滤器链和流控策略。开发者可以根据需求定制路由规则,...
3. **Spring Cloud Gateway**:作为API网关,增加了对WebFlux的支持,提高了性能和可扩展性。 4. **Spring Cloud OpenFeign**:增强了服务调用的灵活性和错误处理能力。 **Spring Cloud OAuth2** OAuth2是一个开放...
**Spring Cloud Gateway** 是Spring Cloud的API网关,它基于Spring Framework 5、Project Reactor和Spring WebFlux构建。Gateway作为一个统一的入口,可以处理所有的微服务路由,实现动态路由、熔断、限流、监控等...
8. **Spring Cloud Gateway**:Spring Cloud 的新一代 API 网关,基于 Spring Framework 5、Project Reactor 和 Spring WebFlux,提供更强大的路由功能和过滤器链。 9. **Spring Cloud LoadBalancer**:替换 Ribbon...
Spring Cloud Gateway作为Spring Cloud生态系统的统一入口,它扮演着API网关的角色。它可以过滤请求、路由到不同的微服务、进行安全控制、负载均衡等功能。通过配置,开发者可以轻松地对所有微服务的流量进行管理和...
Dubbo 社区版提供了高性能的 RPC 调用能力,而 Spring Cloud Gateway 是基于 Spring Framework 和 Spring WebFlux 构建的现代化网关,用于统一处理请求路由、限流、熔断等。 4. **消息中间件**:RocketMQ 是阿里...
Spring Cloud Gateway 是Spring官方推出的一款现代化的网关服务,它构建于Spring Framework 5、Project Reactor 和 Spring Boot 2之上,提供了高性能、易用的API路由管理、过滤器等功能,是Spring Cloud生态中的重要...