拍拍信微服务网关实践分享

背景:

拍拍信作为一家专业的数据服务公司,承载着百亿级数据量,每天支撑着千万级的调用量,对数据的安全、用户需求响应时效、系统的稳定都有着极其严格的要求,在此大前提下,拍拍信踏入微服务化之路。

截止发稿,拍拍信在微服务的道路上已经走过一年有余,90%以上的服务已经投产,整个微服务生态体系也逐渐发挥出不凡的表现,比如快速自动化水平扩展、无值守升级、流量零损耗发布等。

拍拍信网关概述

拍拍信微服务基于Spring Cloud实施落地,由于其已经集成了Netflix Zuul,也符合拍拍信的技术栈, 能满足快速应用和二次开发,其官方对Zuul的定义如下:

Zuul is the front door for all requests from devices and web sites to the backend of the Netflix streaming application. As an edge service application, Zuul is built to enable dynamic routing, monitoring, resiliency and security. It also has the ability to route requests to multiple Amazon Auto Scaling Groups as appropriate.

简单来说,Zuul是所有请求的前端入口,并转发到后端服务,作为一个边缘服务应用,Zuul支持动态路由、监控、弹性和安全。它类似于 Servlet 中过滤器(Filter)的概念,提供了四种过滤器的 API,分别为前置(Pre)、后置(Post)、路由(Route)和错误(Error)四种处理方式,附上标准流程,如下图:

但是Zuul的天生不足也比较明显,需二次开发才可应用于生产环境,首先,它只是一个框架,并不具有运营能力,投产的系统往往都需要一个管控后台,其次因为它是边缘服务应用,所以必须做到稳定、持续服务,也就意味着它是长驻服务,不能因为内部业务升级、新开业务等因素重启网关等。不足之处具体表现为:

● ZUUL自身提供的Monitor&Tracer功能薄弱,无法需足业务需要;

● Spring Cloud虽然集成了ZUUL,但路由表为静态配置,需要运行时增加、修改;

● 不具有http报文拦截、过滤、转换功能;

● 网络属性配置(如:Socket Timeout)没有灵活的API,且是静态配置(这个是Ribbon的锅);

● 本身并没有提供鉴权认证机制、数据安全等功能;

● 运行指标监控、告警功能缺失,虽然可以配套Turbine使用,但也需要二次开发。

最终,经二次开发改进之后的功能模块包括如下:

整体架构如下:

从业务角度出发

拍拍信网关研发之初,实际业务中的一些痛点问题及需求:

● 服务通讯协议多样化,需要业务各自实现,导致代码重复写;

● 接口缺少完善的监控,发现不及时,问题排查慢等,造成业务受损;

●  接口调用记账收费无统一入口,会产生多记、漏记、错记等问题;

● 接口流量突增,影响其他客户的调用,导致用户满意度下降;

● 内部接口的发版等变更时会导致外部接口的调用失败,接口稳定性下降;

● 接口还会受到一些DDoS及漏洞扫描及爬虫等非法访问对网关安全提出新的要求。

Zuul二次开发&业务支撑

●  路由配置管理:

当业务团队数量增多,业务系统数量增加,不断的持续开发、升级、发版、新业务线的开通上生产,完全无法控制API数量,假如每改动一个API、新增一个API都需要配置路由并重启生效,而此时用户的调用还没有结束,强制重启会导致用户方异常,即使可以采用Nginx、Haproxy负载方案解决问题,那么也要配置路由、重启网关,可想系统得多么糟糕。

我们采用将路由信息持久化到数据库中的方案,系统启动时将路由配置加载到内存中,并采用推拉结合的方式,运行时更新内存中数据,达到真正的动态路由。

需注意:系统启动和加载路由配置的先后顺序,要保证系统启动成功时,配置信息已经加载完成,否则因为路由配置不全,用户请求已经到达,会导致部分请求失败。

●  路由配置发布:

很多公司在服务升级发版时,都非常小心谨慎,如履薄冰,即使在线下经过充分测试,也难免到生产环境出事故,为了降低影响面,拍拍信网关提供了路由配置灰度发布、一波流发布、版本回滚功能,可以分批次通过RocketMQ消息通知的方式发布,指定某几个服务节点生效,一旦发现监控指标异常,可以利用版本回滚功能回退到之前版本。

●  协议适配&报文检查、过滤、转换:

做为一家数据服务公司,接口协议类型也是多样化的,如:JSON、XML、HTTP,为了简化业务开发,数据在网关层利用Zuul Filter对报文统一处理,格式化为key/value对后再转发到下游,使内部业务开发标准化。

提供边缘服务,要确保数据正确性,拍拍信网关提供了严格的数据校验配置,比如:数据类型、数据长度、值大小、枚举、时间区间、正则表达式、脚本化支持等,可以滤掉非正常请求,避免内部业务受到冲击。

此外,即便用户传入数据都正确,一些特定业务场景下,仍不能直接将数据转到下游,比如用户传入的参数叫idCard,但是下游需要的参数名是idNumber,这就需要用到参数名称转换功能,甚至可以调用Groovy脚本运算产生参数值,或者添加、修改HTTP请求头信息等。除非下游需要的参数及参数值就是用户传入的数据,这种情况下,我们支持一种面向接口维度的“透传”工作模式。同请求报文处理一样,响应报文也具有“透传”和“转换”功能,以达到接口标准化目的。

●  网络属性配置管理

Spring Cloud集成的Zuul,提供了socket-timeout-millis配置项,Ribbon提供了ReadTimeout配置项,如果要面向API且可以运行时动态调整,原生静态配置达不到需求。

另一点,微服务场景下,服务之间调用错综复杂,要想知道某一次请求来自哪个调用方,实属困难,可以借助来源IP定位,不过更便捷的方法是设置Agent来标记。

●  资源隔离

首先说下限流,目的是保护后端服务,在面对大流量时不致于被压垮,当负载过重时丢弃一部分流量。但是限流是基于服务还是接口,需要根据业务情况慎重考虑。还可以做到按用户、按接口多维度分配资源,避免单用户占用所有线程资源。

当前拍拍信网关结合Ribbon+Hystrix实现按接口维度限流、熔断&降级,资源隔离采用信号量 (推荐使用信号量做资源隔离,原因是Hystrix内部用原子类计数器实现信号量,更轻量,如果采用线程池模式,会导致线程数量陡增,反而增加线程调度的开销。)

另一点需要注意,Hystrix提供了服务超时配置,如果业务多是网络化调用,这种场景下,建议关闭Hystrix的超时功能,改用依SocketTimeOut为准,否则超时配置容易错乱且不易维护。

●  鉴权认证&验签

数据在网络流动过程中,面临被篡改的风险,为削减数据被篡改的负面影响,我们做到按接口维度可视化选择采用数据验签方式,目前支持:MD5、SHA、JWT、TOKEN 4种方式。

●  服务发现

内部业务系统升级时,发布平台自动将对应节点从集群中注销。随着业务量的不断攀升,现有集群不足以支撑业务时,系统会自动水平扩容。

●  运行指标监控&告警及日志

1. 多维度实时监控&告警;

按用户和接口维度监控流量、错误率拦截量,及网关系统运行状态等,如:GC、IO异常、负载均衡度等,通过监控平台配置告警规则、告警渠道等,全天候不间断自动巡检,实时感知业务状态,配合内部值班制度,实时发现用户调用状态并及时联系解决。

2. 边缘服务访问统计&日志记录;

a) 详细记录接口访问的入参、出参,以及内部流转过程、数据,使用Logstash推送到ES,在需要回溯问题时,可得到用户调用时的详细信息及接口返回信息,帮助用户定位问题,做到有据可查。

b) 通过网关管控后台配置接口是否收费记账、记账数据格式,运行时灰度发布动态生效,统一收口收费记账逻辑。

●  微服务迁移过移中的融合

微服务实施需要考虑对业务产生的积极、消极影响,首先要保证业务不能停摆。其次要提供良好的迁移、接入体验,服务好业务团队才能使网关顺利推广、投产,当然也缺不了公司绩效压力,在整个网关推进过程中,包含以下几个阶段:

1. 纯代理模式阶段:承载全网所有流量并转发到下游,但不参与业务过程,经过流量洗礼后更加提升了产品信心;

2. 代理和工作模式并存:业务工程迁移是个漫长的过程,可能要经过数周数月,所以由业务团队决定接口在哪种模式运行;

3. 纯工作模式&复合阶段:在经过前两个阶段后,大多数接口已经接入网关,这时候网关不仅承担了流量入口,还承担了业务入口的角色,通用、全局的业务规则由网关负责执行处理。

总结:

兵马未动,粮草先行,是为了解决后顾之忧,软件产品除了满足业务需求之外,更需要关注的是产品体验,运行状态反馈、业务状态反馈等,从而促进产品优化,再优化以达到最佳状态。可用性基本决定了产品的口碑,而可运营则给产品增加了生命的魔力,管控&监控更是验证产品的运行表现是否符合预期。

期待后续:

●  基于网关配置,生成Swagger Api 文档

●  微服务治理

●  链路跟踪

欢迎有兴趣的小伙伴通过以下方式咨询我司相关产品。

电话:021 5083 0898

邮箱:PPCBD@ppcredit.com

地址:上海市浦东新区张江丹桂路999号G1栋