API 网关从入门到放弃

国内新闻 阅读(1179)

假设您正在开发一个电子商务网站,那么会有很多后端微服务,例如会员,商品,推荐服务等。

2a85f14d2ee144e689a278ee7d34c5ab

那么这里会出现问题,APP/Browser如何访问这些后端服务?

每个企业都需要逻辑,例如身份验证,限流和权限检查。如果每个企业都在为自己而战,那么制造自己的车轮将会非常痛苦。它可以被提取并放在一个统一的地方。如果业务量相对简单,这种方法在早期阶段就没有任何问题,但随着业务变得越来越复杂,如淘宝和亚马逊打开一个页面,它可能涉及数百个微服务一起工作,如果每个微服务如果你分配一个域名,一方面,客户端代码将难以维护,涉及数百个域名,另一方面,连接号码的瓶颈。想象一下,您打开一个应用程序,通过数据包捕获发现数百个远程调用。这在移动端非常低效。线路上的每个新服务都需要操作和维护才能参与,申请域名,配置Nginx等。当涉及到在线和离线服务器时,它还需要操作和维护才能参与。此外,使用域名,这对环境不友好。呼叫者需要根据域名自行判断。还有另一个问题。后端的每个微服务都可以用不同的语言编写,并采用不同的协议,如HTTP,Dubbo,GRPC等,但是你不能要求客户端适应这么多的协议。这是一项非常具有挑战性的工作,项目可能非常复杂且难以维护。如果你需要在后期重构微服务,它将变得非常麻烦。您需要客户与您合作进行转型,例如商品服务。随着业务变得越来越复杂,以后需要将其拆分为多个微处理器。服务,此时外部提供的服务还需要分成多个,而客户端需要配合你进行转换,这是非常痛苦的。

API网关

37c61a34ccf54174afaecb8aa347d51e

更好的方法是使用API网关实现API网关以接管所有入口流量。与Nginx的角色类似,将所有用户请求转发到后端服务器,但网关不仅仅是简单转发,还包括流量。做一些扩展,如身份验证,流量限制,权限,保险丝,协议转换,错误代码统一,缓存,日志记录,监控,报警等,以便提取一般逻辑,网关统一,以及业务方面可以专注于业务逻辑,以提高迭代效率。

通过引入API网关,客户端只需要与API网关进行交互,而无需与每个业务方的接口进行通信。但是,引入一个组件会引入潜在的故障点,因此实现了高性能和稳定的网关。还涉及许多要点。

bb98020ae61d462394c138442325ecaa

API注册

服务提供商如何访问网关?通常有几种方法。

第一种类型使用插件扫描业务方的API,例如Spring MVC的注释,并结合Swagger的注释来实现参数验证,文档和&和SDK生成等。扫描完成后,需要报告到网关的存储服务。手动输入。例如,接口的路径,请求参数,响应参数,调用方法等,但这种方法比较麻烦。如果参数太多,早期进入将是耗时且费力的。

6ff110259aca4f32920b880a4c1fdc70

资料导入。例如,通过Swagger \ OpenAPI等,如阿里巴巴云的网关:

f79624d0e25e406491a25c2ea00d7489

协议转换

内部API可以通过许多不同的协议实现,例如HTTP,Dubbo,GRPC等,但是其中许多协议对用户不是很友好,或者根本没有公开,例如Dubbo服务,所以他们需要在网关层。做一个协议转换,用户的HTTP协议请求,在网关层进入底层对应的协议,如HTTP - > Dubbo,但这里需要注意很多问题,比如参数类型,如果类型错误,导致转换问题如果日志不够详细,则难以找到问题。

服务发现

作为流量的网关,网关负责转发请求,但首先需要知道转发给谁,如何解决,有几种方法:

Written in the code/configuration file, this method is quite frustrating, but it can also be used. For example, the physical machine is still used on the line, the IP change will not be very frequent, but the expansion and contraction, including the application of the line and the line will be very troublesome. The gateway itself even needs to implement a health monitoring mechanism. domain name. Adopting a domain name is also a good solution. It is applicable to all languages, but for internal services, domain names can be very inefficient, and environmental isolation is not very friendly. For example, pre-issue and online are usually the same database, so The gateway may read the same domain name. At this time, the pre-launched gateway calls the online service. Registration center. Adopting the registration center will not have these problems. Even in the container environment, the IP change of the node is frequent, but the real-time maintenance of the node list will be done by the registration center, transparent to the gateway, and the normal application of the application. Including abnormal downtime, etc. it will also be detected by the health check mechanism of the registration center and feedback to the gateway in real time. And there is no additional performance loss in the performance of the registry. In the domain name mode, you need to take a DNS resolution, Nginx forwarding, etc. There is a lot of hops in the middle, and the performance will be greatly reduced, but the registration center, the gateway is The business side directly communicates point-to-point without any additional loss.

Service call

Because gateways are connected to many different protocols, you may need to implement a variety of calling methods, such as HTTP, Dubbo, etc. For performance reasons, it is best to use asynchronous methods, while Http and Dubbo support asynchronous, such as apache. An asynchronous HTTP client based on NIO implementation.

xx因为网关会涉及很多异步调用,如拦截器,HTTP客户端,dubbo,redis等,所以你需要考虑异步调用的方式,如果基于回调或期货,代码嵌套会很深,可读性差可以基于响应式转换,参考zuul和spring cloud网关解决方案。

优雅离线

优雅的下线也是网关需要注意的问题。网关的底层将涉及许多协议,例如HTTP和Dubbo,并且HTTP可以继续细分,例如域名,注册中心等。其中一些支持优雅的离线,例如Nginx。它支持健康监测机制。如果检测到某个节点已被挂起,则该节点将被删除。要使应用程序脱机,必须组合发布系统,首先是逻辑脱机,然后是后续Nginx的运行状况。监视请求直接返回到失败(例如,直接返回到500),然后等待一段时间(取决于Nginx配置),然后实际丢弃应用程序。此外,注册中心也是类似的。通用注册中心仅支持手动离线。您可以调用注册中心的界面,在逻辑脱机阶段将节点脱机。有些不支持主动离线。您需要组合缓存。用于延迟应用程序脱机的配置。此外,其他原则如Dubbo也是如此。

性能

网关是所有流量的门户,性能至关重要。大多数早期网关是基于同步阻塞模型构建的,例如Zuul 1.x.但是这个同步模型我们都知道,每个请求/连接都会占用一个线程,并且线程是JVM中非常繁重的资源,比如Tomcat默认是200个线程,如果网关隔离没有完成,当它发生的时候网络延迟,FullGC,慢速第三方服务等导致上游服务被延迟,线程池很容易填满,导致新请求被拒绝。但是,此时,IO上的所有线程都被阻塞,并且未获得系统资源。指定。另一点是它容易受到网络,磁盘IO和其他延迟的影响。您需要小心设置超时时间。如果设置不正确且服务隔离不完美,则可以通过慢速接口轻松拖动网关。

连接使用的资源变得非常低,系统可以同时处理大量请求。

如果是JVM平台,Zuul 2,Spring Cloud网关等都是很好的异步网关选择,也可以基于Netty,Spring Boot 2.x webflux,vert.x或servlet 3.1异步支持自行开发。

高速缓存

对于一些幂等的get请求,您可以根据服务端指定的缓存头在网关级别创建一层缓存,并将其存储在二级缓存(如Redis)中。这样的重复请求可以在网关层直接处理而不会出现问题。业务线减少了业务方面的压力。此外,如果业务节点挂起,网关也可以返回自己的缓存。

限流

对于每个业务组件,可以说当前限制是必要组件。如果当前限制不好,当请求量突然增加时,很容易导致服务方的服务挂起,如双11,双12当时间很大时,接口请求的数量是几次是正常的。如果未评估容量且未实施电流限制,则可以轻松地为整个服务提供服务。因此,流量限制策略需要基于服务提供者接口的处理能力。我相信当淘宝和百度抢红包时,每个人都看到了降级页面。

因此,必须在接入层实施流量限制策略。非核心接口可以直接降级,以确保核心服务的可用性。对于核心接口,需要根据压力测量过程中获得的接口容量建立相应的流量限制策略。电流限制分为几种类型。

单机。单机性能相对较高,不涉及远程调用,只涉及本地计数,对接口RT的影响最小。但是,您需要考虑下限流数的设置,例如,是针对单个网关还是整个网关集群。如果是整个群集,则需要在网关收缩或扩展时考虑相应的流量限制。分散式。 Distributed需要一个存储节点来维护当前接口的调用次数,例如redis,sentinel等。这种方法会因远程调用而导致性能下降,还需要考虑存储挂起的问题,如redis如果挂断,网关需要考虑降级方案,是否降级到本地电流限制,还是直接降级电流限制功能本身。

此外,还有不同的策略。简单计数,令牌桶等。在大多数情况下,简单计数就足够了,但如果需要支持突发流量等场景,则可以使用令牌桶。您还需要考虑哪些限制,例如IP,接口,用户维度或请求参数中的某些值。这里可以使用表达式,这是相对灵活的。

稳定性

稳定性是网关的一个非常重要的部分。需要很好地进行监控和报警,例如接口呼叫量,响应时间,异常,错误代码,成功率和其他相关监控报警,以及线程池相关。例如,活动线程数,队列积压等,还有一些系统级,如CPU,内存,FullGC等基本。

网关是所有服务的入口点。网关的稳定性要求高于其他服务。最好稳定运行并尽可能少地重新启动。但是,在添加新功能或添加日志以解决问题时,这是不可避免的。需要重新发布,所以你可以参考zuul方式,所有核心功能都是基于不同的拦截器,拦截器代码是用Groovy编写的,存放在数据库中,支持动态加载,编译,运行,这是一个问题吧可以首先定位和解决,如果网关需要开发新功能,它只需要添加一个新的拦截器并动态添加到网关,而无需重新发布。

融化降级

保险丝机构也是非常重要的一种。如果服务挂起,接口响应严重超时等,整个网关可能被接口拖动。因此,有必要增加排污。当发生特定异常时,网关直接降级接口,可以基于Hystrix或Resilience4j实现。

登录

由于所有请求都由网关处理,因此日志需要相对完整,例如接口的时间消耗,请求方法,请求IP,请求参数,响应参数(注意脱敏)等,以及可能涉及很多微服务,因此您需要提供统一的traceId以便轻松关联所有日志,您可以将此traceId放在响应头中以方便故障排除。

隔离

例如,线程池,http连接池和redis的应用程序层隔离。另外,核心服务部署可以根据服务场景与其他非核心服务分离。

网关管理平台

这也是一个非常重要的部分。您需要考虑整个过程的用户体验。例如,访问网关的过程可以简化和智能化。例如,如果它是dubbo接口,我们可以通过转到git存储库来获取源代码。分析相应的类和方法,实现自动填充,尽量帮助用户减少操作;另外,界面一般来自test-> pre-post->在线,如果每次都要填写表格,那将非常麻烦,我们可以自动完成此事。此外,如果网关部署在多个可用区甚至不同的国家,那么我们需要接口数据同步功能。否则,用户需要去每个背景再次操作,这非常麻烦。

此个人推荐是直接参考阿里巴巴云,Aws等提供的网关服务,功能非常全面。

3b844c2b-5a18-40bf-9e12-5d4a927678c9

其他

还有其他需要考虑的问题,例如界面模拟,文档生成,sdk代码生成,错误代码统一,服务治理等,这些并不详尽。

总结

当前网关仍然是集中式架构。所有请求都需要通过网关一次。因此,当流量突然增加或流量突然增加时,网关可能成为性能瓶颈,并且当网关访问大量接口时,进行流量。评估不是一件容易的事。每次你想要这样做,你需要与业务部门一起在接口上进行压力测量,评估大致容量,扩展网关,网关是所有流量的入口,所有请求都是由网关处理,准确估计容量很复杂。您可以参考当前流行的ServiceMesh,采用分散式方案,并将网关逻辑吸入边车。 sidecar和应用程序部署到同一节点,并接管流入和流出应用程序的流量。对于相关的业务压力测量和有针对性的扩展,升级将更加顺畅,集中式网关,即使灰度级发布,理论上,业务方的所有流量都将流入新版本的网关,如果是out该问题将影响所有业务,但这种分散方法可以首先针对非核心业务进行升级。在观察问题一段时间后,它将被推送到网上。此外,ServiceMesh的解决方案对多语言支持也更友好。