企业宣传,产品推广,广告招商,广告投放联系seowdb

如何通过用户网关和缓存降低研发成本 网关编程

如果说用户的流量就像波涛汹涌的海浪,那网关就是防御冲击的堤坝。在大型的互联网项目里,网关必不可少,是我们目前最好用的防御手段。通过网关,我们能把大量的流量分流到各个服务上,如果配合使用 Lua 脚本引擎提供的一些能力,还能大大降低系统的耦合度和性能损耗,节约我们的成本。一般来说,网关分为外网网关和内网网关。外网网关主要负责做限流、入侵预防、请求转发等工作,常见方式是使用 Nginx + Lua 做类似的工作;而最近几年,内网网关发展出现了各种定制功能的网关,比如 ServiceMesh、SideCar 等方式,以及类似 Kong、Nginx Unit 等,它们的用途虽然有差异,但是主要功能还是做负载均衡、流量管理调度和入侵预防这些工作。

外网网关功能

我们先从外网网关的用法说起,我会给你分享两类外网网关的实用设计,两个设计可以帮助我们预防入侵和接触业务的依赖。

蜘蛛嗅探识别

在处理大流量网站时,常见的安全问题包括非法引用和机器人抓取。为了防止这些问题,我们可以采取一些有效的策略,例如通过网关实现限速和入侵检测功能。

机器人抓取防范:机器人抓取是另一个常见的问题。为了识别和防止机器人的抓取,我们可以采取以下几种方法:

通过这些措施,我们可以有效应对非法引用和机器人抓取问题,保护网站的资源和数据安全。同时也能保持对搜索引擎的友好性,保证 SEO 的正常运作。

网关鉴权与用户中心解耦

之前我们讨论了如何利用网关来阻挡非法用户的骚扰。实际上,网关除了防御攻击、防止资源被恶意消耗外,还能帮助我们解除一些业务依赖。比如在用户登录的设计上,每个业务不需要直接依赖用户中心来验证用户的合法性。

用户鉴权通常会通过在各个子业务中集成用户中心的 SDK 来实现一致的校验逻辑。这种方式带来便利的同时,也产生了新的问题:SDK 的同步依赖和升级维护。基础公共组件一般会通过 SDK 为业务开发提供便捷,而如果仅通过 API 提供服务,一些特殊的操作可能会需要重复实现。然而,一旦 SDK 发布,我们就需要做好同时维护多个版本 SDK 在线工作的准备,以确保兼容性和功能稳定。

以下图展示了使用 SDK 鉴权 token 方式和直接通过用户中心接口进行鉴权的效果对比:

在集成 SDK 的情况下,各业务可以自行校验用户身份,无需频繁请求用户中心。然而,这种方案也带来了一些挑战。由于 SDK 是嵌入在各个项目中的组件,项目通常不会频繁升级其版本来保持稳定性。这使得用户中心的后续升级面临阻力,因为升级时必须考虑到所有依赖的业务。每次基础服务的大规模升级都需要大量人力来同步更新 SDK,从而增加了维护的复杂性。

为了解决这种耦合问题,我们可以考虑另一种设计思路,即将用户登录鉴权功能放到网关层。这样一来,业务系统不再需要直接依赖用户中心的 SDK,而是通过网关完成身份验证和权限校验。通过这种方式,网关可以在接收到请求时直接进行用户鉴权,只有通过验证的请求才会被转发至具体的业务服务,从而解耦了用户中心与各业务系统的直接依赖关系。

以下图所示为这一设计下的请求流程,请结合示意图参考,我将进一步分析其工作机制和优点。

结合上图,我们来看这种设计的实现流程。当用户请求业务接口时,网关首先会对请求用户的身份进行鉴定。如果通过验证,用户信息会被放入 header 并传递给后端服务,而业务 API 无需关注用户中心的实现细节,直接从 header 中获取用户信息即可继续工作。

如果业务要求用户必须登录才能使用,可以在业务逻辑中增加一个判断,检查请求 header 是否包含 uid。若缺少 uid,则返回统一的错误码给前端,提示用户需要先登录。这种鉴权服务设计有效解耦了业务模块和用户中心。即使用户中心逻辑变更,也无需业务模块同步升级。

此外,除了基本的登录鉴权,这种设计还可以在网关层实现更加灵活的权限管理。例如,可以为某些域名开启基于角色的访问控制(RBAC)或基于属性的访问控制(ABAC),为不同的业务场景量身定制权限控制策略。通过网关,我们还可以为不同用户提供不同权限的功能,支持灰度测试等高级功能,从而提高系统的灵活性和安全性。

内网网关服务

了解了外网的两种妙用,我们再看看内网的功能。它可以提供失败重试服务和平滑重启机制,我们分别来看看。

失败重试

在项目发布升级或服务发生故障重启时,系统可能会短暂不可用。这段期间如果有用户请求,可能会因为后端未响应而返回 504 错误,影响用户体验。为提升用户体验,可以利用内网网关的自动重试功能。

当请求到达后端,但因服务返回 500、403 或 504 等错误时,网关可以避免立即返回错误。相反,网关可以让请求稍作等待,之后再重试;或者直接返回之前缓存的内容。通过这种方式,业务能够实现平滑的热更新,让服务看起来更为稳定,使用户不会明显感知到线上升级过程中的波动。

平滑重启

在服务升级过程中,平滑重启机制能够避免服务进程在接收到 kill 信号后立即退出。具体做法是先让服务停止接收新的请求,同时等待当前正在处理的请求完成。如果请求处理超时(比如超过 10 秒),则强制退出服务。这种机制有助于保证正在进行的请求得到妥善处理,减少服务中断对用户的影响。

通过这个机制,用户请求处理就不会被中断,这样就能保证正在处理中的业务事务是完整的,否则很有可能会导致业务事务不一致,或只做了一半的情况。有了这个重试和平滑重启的机制后,我们可以随时在线升级发布我们的代码,发布新的功能。不过开启这个功能后,可能会屏蔽一些线上的故障,这时候可以配合网关服务的监控,来帮我们检测系统的状态。

内外网关综合应用

首先来看网关接口缓存功能,也就是利用网关实现一些接口返回内容的缓存,适合用在服务降级场景,用它短暂地缓解用户流量的冲击,或者用于降低内网流量的冲击。具体实现如下图所示:

通过上图,我们可以看到,网关的缓存机制通常是通过临时缓存和 TTL(生存时间)方式来实现的。当用户请求某个服务接口时,如果该接口的响应已被缓存,并且缓存没有过期,网关就会直接返回缓存的数据给客户端。这种方法能够显著减轻后端数据服务的负担。

然而,这种方式的选择是经过权衡的,它牺牲了数据的强一致性以换取性能上的提升。同时,缓存机制对性能要求较高,必须确保网关缓存能够处理外部流量的高 QPS(每秒查询数)。为了避免过多的穿透流量,可以定期通过脚本刷新缓存数据。这样,当网关发现有有效的缓存时,就直接返回;如果缓存没有命中,才会请求后端服务,并缓存结果。

这种实现方式比单纯依赖缓存更为灵活,能够提高数据一致性,但同时也增加了开发和维护的复杂度,需要额外的代码和运维来确保系统的稳定性和数据的一致性。

当然这种缓存的数据长度建议不超过 5KB(10w QPS X 5KB = 488MB/s),因为数据太长,会拖慢我们的缓存服务响应速度。

服务监控

最后,我们来讨论利用网关进行服务监控的问题。在没有链路跟踪的情况下,大多数系统的监控通常依赖于网关的日志。通过分析网关的访问日志中的 HTTP 状态码,我们可以判断服务是否正常运行。同时,结合请求的响应时间信息,我们能够实现基本的系统监控功能。

具体来说,网关的访问日志会记录每个请求的 HTTP 状态码(如 200、500、404 等)和响应时间。这些信息可以帮助我们监控服务的健康状况,例如判断是否有异常的错误码(如 500 错误)或请求超时,进而及时发现潜在问题。

下面的图示展示了如何通过网关来监控服务的运行状态,请结合图示进行进一步理解,我会继续分析这个过程的细节。

为了更方便地判断线上服务状况,可以先对信息进行统计。具体方法是定期聚合访问日志中的错误,并汇总不同接口的请求错误数量。例如,通过聚合后我们可以得到类似的数据:“30秒内发生 500 错误 20 次,504 错误 15 次,某域名接口响应时间超过 1 秒的情况 40 次”。这些统计数据帮助我们快速分析服务的健康状态。

与其他监控方式不同,网关监控能够覆盖所有业务,虽然监控的粒度较粗,但仍然是一个有效的方案。如果结合 Trace,我们可以在访问日志中记录 Trace ID,通过这些 ID 进一步排查问题的具体原因。这种实现方式在一些公司(如好未来和极客时间)已经得到了应用,提高了故障排查的便利性。

© 版权声明
评论 抢沙发
加载中~
每日一言
不怕万人阻挡,只怕自己投降
Not afraid of people blocking, I'm afraid their surrender