13

58安居客二手房 API Gateway Sidecar 实践

 3 years ago
source link: https://mp.weixin.qq.com/s?__biz=MzI1NDc5MzIxMw%3D%3D&%3Bmid=2247491133&%3Bidx=1&%3Bsn=2f3bf5e940fee28ca64ed02c508514da
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

导读

58安居客二手房业务线的技术架构合并后,许多老页面需要逐步的重构成同一套技术体系,Web端采用NodeJs渲染,App后端API采用Java,再加上部分老的页面仍然使用的PHP。我们在对外接口这一层有很多通用的拦截功能,例如签名验证、用户票据验签、反爬虫拦截、公共参数处理、城市域名解析等。3套不同的技术栈意味着这些功能都要用不同的语言重复开发3遍,各端逻辑难以统一和维护,面临不少困难,因此亟需一个API网关能够统一的处理这些逻辑,降低维护成本。

背景

58安居客二手房业务线的技术架构合并后,许多老页面需要逐步的重构成同一套技术体系,Web端采用NodeJs渲染,App后端API采用Java,再加上部分老的页面仍然使用的PHP。我们在对外接口这一层有很多通用的拦截功能,例如签名验证、用户票据验签、反爬虫拦截、公共参数处理、城市域名解析等。3套不同的技术栈意味着这些功能都要用不同的语言重复开发3遍,各端逻辑难以统一和维护,面临不少困难,因此亟需一个API网关能够统一的处理这些逻辑,降低维护成本。

API Gateway 选型

考虑到会有很多定制需求,加上二手房技术团队本身对Java比较熟悉,因此直接选择了Java技术栈下的解决方案。主要有3种:

  • 基于Netty定制

  • Spring Cloud Zuul

  • Spring Cloud Gateway

网关作为所有流量的入口,对于吞吐量、稳定性、请求延迟、资源占用都有着更高的要求。Zuul是基于Servlet的同步线程模型,不可避免的容易存在一些IO阻塞的场景导致线程频繁切换、线程阻塞等问题。而纯异步的线程和IO模型,能够减少线程开销、避免IO阻塞,因此在网关上Netty定制和Spring Cloud Gateway都是更好的选择

而Netty定制需要比较多的开发资源投入,二手房技术团队重心还是在业务项目上,没有太大精力完全自研。最终我们选择了底层同样基于Netty的Spring Cloud Gateway

Spring Cloud Gateway是Spring Cloud最新的网关组件,底层基于Project Reactor和Spring Webflux构建。Project Reactor提供了一套响应式编程风格的API以及底层基于Netty的异步网络请求模型,能够提供一套纯异步的编程和运行环境,在高并发的场景下能够比较好的利用CPU资源,避免出问题时大量线程阻塞的问题。

什么是API Gateway Sidecar

传统的网关部署模式下,一般是外网流量进来以后直接进入到网关层,网关处理通用逻辑之后,再将流量转发给后端的业务服务器

IZfeyy6.png!mobile

但是58的运维架构如果要改成上述这种模式,成本风险都比较大,而且短期内只有房产二手房业务线一个团队有这样的需求。另外对接容器云平台的服务发现功能也比较复杂,短期内可行的架构如下:

bErMRrA.png!mobile

但是这种模式很快就被我们否定了,内网流量增加3倍,运维成本和系统稳定性都增加了很多不确定性。因此需要寻找一个既能满足我们的需求,又能适配当前58的运维和容器云平台架构的模式

我们将目光瞄向了Service Mesh架构中的Sidecar模式。Sidecar模式是在容器内部部署了一个Sidecar进程,流量先经过Sidecar代理,完成鉴权、日志、服务注册发现等功能。参考Sidecar模式,我们可以在容器内部署一个API Gateway进程,拦截进来的http流量,进行处理后再转发到原来的web进程。于是我们的部署结构如下:

RFr2iaQ.png!mobile

这样在现有的运维和容器云架构下能够完美的实现我们需要的功能,流量和运维成本都没有太大的增加,我们只需要处理好Sidecar进程的监控即可

容器内Gateway进程部署

公司的云平台提供了启动脚本的钩子和自定义上传文件的功能,我们可以很轻松的实现网关安装包的安装和进程启动。不过Gateway进程的监控和容器关闭的钩子目前没有直接支持,已经和云平台的同学提需求后续考虑支持

Java版本选择了JDK 11,对G1 GC延迟有比较大的优化,能够减少GC对网关的影响。Gateway进程内部本身没有太多的大内存使用,我们也希望资源能够占用尽量少一点,因此JVM堆大小选择了512MB

最后结合云平台提供的镜像商店,我们将这些功能都集成到一起放到一个基础镜像中。这样业务集群需要接入的时候直接继承Gateway的镜像即可。后续镜像的维护升级也可以由Gateway负责的同学统一安排

功能定制,模板化

在最初的版本上我们主要实现了4个功能

  • http跳转https

  • 用户登陆票据验证

  • 城市域名、路径解析

  • 反爬虫服务接入

需要注意的是以上功能都需要同时支持58和安居客两个网站

功能开发上,由于二手房之前积累了不少CompletableFuture的使用经验,因此Reactor的Mono/Flux API上手起来还比较快。用户登陆的票据验证,由于云账号只提供了同步版本的SDK,因此我们暂时使用了线程池来兼容,后续云账号会提供支持异步版本的SDK供我们集成。反爬虫则基于SCF的异步调用来实现。

由于不同域名(58.com/anjuke.com)、不同平台(web/app/小程序)城市解析还有反爬参数都不同,我们提供了模板化的预定义配置文件,业务方在接入时只需要根据当前集群支持的域名,直接引入模板配置即可快速上线

性能压测

我们使用ab对网关进行了压测,测试方式为网关在处理完上述4个功能的逻辑后直接返回200给请求方,流量不经过业务进程。

测试容器为4核4G的云平台容器:

并发数 P99 最慢请求 QPS 4 4

20ms

1500

8 7 30ms 2100 16 11 35ms 2200

4并发发的情况下,P99 4ms的性能开销完全满足我们的业务需求。 8并发时 也有不错的性能,而且4核单机2000 QPS至少能保证网关进程性能是远超过业务的Node/Java/PHP进程的

GC方面,Young GC基本维持在2~5ms,约1300次请求一次Young GC,对性能的影响目前来说没有太大问题。另外我们压测了大约近百万次请求都没有发生Mix GC,Old区的堆大小一直也比较稳定的维持在25%左右。

上线实测

完成上述这些步骤后,我们开始在线上的集群实际的测试。我们先选取了一个流量很小的集群完成线上的初步验证后,开始在二手房业务mobile web最核心的二手房详情页进行应用。这个页面本身是使用NodeJs运行的

实际上线后,由于NodeJs中反爬、获取票据的逻辑都迁移到了Gateway中,整体的页面性能,平均速度提升了20%+,p95性能提升5~10%。

yEJRnmY.png!mobile

E7Nr6fv.png!mobile

更为重要的是,之前的NodeJs在高峰期或者遭到爬虫突然的大量请求时,响应时间的波动非常大。Gateway上线以后有效的平抑了这部分波动,减轻NodeJS进程的压力。

IFja6v3.png!mobile

资源使用方面,CPU占用平均增加约5%,内存占用增加不到1G。

监控方面,由于初期规模较小,目前只是依赖了Spring Boot Admin来进行简单的监控,后续这方面需要投入比较大的精力迭代。

总结及后续优化

目前这套Gateway已经在房产二手房业务线多个NodeJs和Java集群上线,给业务开发同学,特别是前端的同学减轻了不少维护成本。

后续的优化方向上主要是在性能、监控、通用化上进行优化

  1. 性能方面主要是优化日志的打印,进一步降低CPU开销以及GC频率的降低

  2. 监控上未来需要加强Gateway进程可用性的监控,避免假死;以及报警手段的加强

  3. 通用化上,我们希望这个组件能够更加的可定制化和可扩展,方便其他业务线的团队有需求时能够快速的应用上线

作者简介:

董菲:房产事业群--二手房用户技术部 后端架构师

推荐阅读:

从Mach-O角度谈谈Swift和OC的存储差异

福利环节

为了鼓励优质内容传播,【58技术】公众号近期会持续推出不定期活动奖励。

  1. 评论区参与话题讨论,#前后端交互的痛点#

  2. 将抽取三个优质评论,送出定制版新年代码台历一本

  3. 活动时间:截至2021年1月24日

FjIrYjb.jpg!mobile

Nb2iMvQ.jpg!mobile


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK