http://www.tuicool.com/articles/rIbUzyj

业务的快速增长,要求系统在快速迭代的同时,保持很好的扩展性和可用性。其中,交易系统除了满足上述要求之外,还必须保持数据的强一致性。对系统开发人员而言,这既是机遇,也是挑战。本文主要梳理大众点评支付渠道网关系统在面对这些成长烦恼时的演进之路,以及过程中的一些思考和实践。

在整个系统的演进过程中,核心思路是:大系统做小,做简单(具体描述可参考《高可用性系统在大众点评的实践与经验》)。在渠道网关系统实践过程中,可以明显区分出几个有代表性的阶段。

一、能用阶段

早期业务流量还不是很大,渠道网关系统业务逻辑也很简单,一句话总结就是:让用户在交易的时候,能顺利把钱给付了。做的事情可简单概括成3件:发起支付请求、接收支付成功通知以及用户要求退款时原路退回给用户的支付账户。这个阶段系统实践比较简单,主要就是“短、平、快”,快速接入新的第三方支付渠道并保证能用。系统架构如图1。

二、可用阶段

在系统演进初期的快速迭代过程中,接入的第三方支付渠道不多,系统运行还算比较平稳,一些简单问题也可通过开发人员人工快速解决。但随着接入的第三方支付渠道不断增多,逐渐暴露出一些新的问题:

(1) 所有的业务逻辑都在同一个物理部署单元,不同业务之间互相影响(例如退款业务出现问题,但是与此同时把支付业务也拖垮了);

(2) 随着业务流量的增大,数据库的压力逐渐增大,数据库的偶尔波动造成系统不稳定,对用户的支付体验影响很大;

(3) 支付、退款等状态的同步很大程度上依赖第三方支付渠道的异步通知,一旦第三方支付渠道出现问题,造成大量客诉,用户体验很差,开发、运营都很被动。

针对(1)中的业务之间互相影响问题,我们首先考虑进行服务拆分,将之前一个大的物理部署单元拆成多个物理部署单元。有两种明显的可供选择的拆分策略:

  • 按照渠道拆分,不同的第三方支付渠道独立一个物理部署单元,例如微信一个部署单元,支付宝一个部署单元等;
  • 按照业务类型拆分,不同的业务独立一个物理部署单元,例如支付业务一个部署单元,退款业务一个部署单元等。

考虑到在当时的流量规模下,支付业务优先级最高,退款等业务的优先级要低;而有些渠道的流量占比很小,作为一个独立的部署单元,会造成一定的资源浪费,且增加了系统维护的复杂度。基于此,我们做了一个符合当时系统规模的trade-off:选择了第2种拆分策略 — 按照业务类型拆分。

针对(2)中的DB压力问题,我们和DBA一起分析原因,最终选择了Master-Slave方案。通过增加Slave来缓解查询压力;通过强制走Master来保证业务场景的强一致性;通过公司的DB中间件Zebra来做负载均衡和灾备切换,保证DB的高可用性。

针对(3)中的状态同步问题,我们对不同渠道进行梳理,在已有的第三方支付渠道异步通知的基础上,通过主动查询定时批量同步状态,解决了绝大部分状态同步问题。对于仍未同步的少量Case,系统开放出供内部使用的API,方便后台接入和开发人员手动补单。

在完成上述的实践之后,渠道网关系统已达到基本可用阶段,通过内部监控平台可以看到,核心服务接口可用性都能达到99.9%以上。演化之后的系统架构如图2。

三、柔性可用阶段

在解决了业务隔离、DB压力、状态同步等问题后,渠道网关系统度过一段稳定可用的时期。但架不住业务飞速增长的压力,之前业务流量规模下的一些小的系统波动、流量冲击等异常,在遭遇流量洪峰时被急剧放大,最终可能成为压垮系统的最后一根稻草。在新的业务流量规模下,我们面临着新的挑战:

(1) 随着团队的壮大,新加入的同学在接入新的渠道或者增加新的逻辑时,往往都会优先选用自己熟悉的方式完成任务。但熟悉的不一定是合理的,有可能会引入新的风险。特别是在与第三方渠道对接时,系统目前在使用的HTTP交互框架就有 JDK HttpURLConnection/HttpsURLConnection、Httpclient3.x、Httpclient4.x(4.x版本内部还分别有使用不同的小版本)。仅在这个上面就踩过好几次惨痛的坑。

(2) 在按业务类型进行服务拆分后,不同业务不再互相影响。但同一业务内部,之前流量规模小的时候,偶尔波动一次影响不大,现在流量增大后,不同渠道之间就开始互相影响。例如支付业务,对外统一提供分布式的支付API,所有渠道共享同一个服务RPC连接池,一旦某一个渠道的支付接口性能恶化,导致大量占用服务RPC连接,其他正常渠道的请求都无法进来;而故障渠道性能恶化直接导致用户无法通过该渠道支付成功,连锁反应导致用户多次重试,从而进一步导致恶化加剧,最终引起系统雪崩,拒绝服务,且重启后的服务还有可能被大量的故障渠道重试请求给再次击垮。

(3) 目前接入的第三方支付渠道,无论是第三方支付公司、银行或是其他外部支付机构,基本都是通过重定向或SDK的方式引导用户完成最终支付动作。在这条支付链路中,渠道网关系统只是在后端与第三方支付渠道进行交互(生成支付重定向URL或预支付凭证),且只能通过第三方支付渠道的异步通知或自己主动进行支付查询才能得知最终用户支付结果。一旦某个第三方支付渠道内部发生故障,渠道网关系统完全无法得知该支付链路已损坏,这对用户支付体验造成损害。

(4) 现有的渠道网关的DB,某些非渠道网关服务仍可直接访问,这对渠道网关系统的DB稳定性、DB容量规划等带来风险,进而影响渠道网关系统的可用性,内部戏称被戴了“绿帽子”。

(5) 对于退款链路,系统目前未针对退款异常case进行统一收集、整理并分类,且缺乏一个清晰的退款链路监控。这导致用户申请退款后,少量用户的退款请求最终未处理成功,用户发起客诉。同时由于缺乏监控,导致这种异常退款缺乏一个后续推进措施,极端情形下,引起用户二次客诉,极大损害用户体验和公司信誉度。

为最大程度解决问题(1)中描述的风险,在吸取踩坑的惨痛教训后,我们针对第三方渠道对接,收集并整理不同的应用场景,抽象出一套接入框架。接入框架定义了请求组装、请求执行、响应解析和错误重试这一整套网关交互流程,屏蔽了底层的HTTP或Socket交互细节,并提供相应的扩展点。针对银行渠道接入存在前置机这种特殊的应用场景,还基于Netty抽象出连接池(Conn Pool)和简单的负载均衡机制(LB, 提供Round Robin路由策略)。不同渠道在接入时可插入自定义的组装策略(扩展已有的HttpReq、HttpsReq或NettyReq),执行策略[扩展已有(Http、Https或Netty)Sender/Receiver],解析策略(扩展已有的HttpResp、HttpsResp或NettyResp),并复用框架已提供的内容解析(binary/xml/json parser)、证书加载(keystore/truststore loader)和加解密签名(encrypt/decrypt/sign/verify sign)组件,从而在达到提高渠道接入效率的同时,尽可能减少新渠道接入带来的风险。接入框架的流程结构如图3。

为解决问题(2)中渠道之间相互影响,一个简单直观的思路就是渠道隔离。如何隔离,隔离到什么程度?这是2个主要的问题点:

  • 如何隔离 考虑过将支付服务进一步按照渠道拆分,将系统继续做小,但是拆分后,支付API的调用端需要区分不同渠道调用不同的支付API接口,这相当于将渠道隔离问题抛给了调用端;同时拆分后服务增多,调用端需要维护同一渠道支付业务的多个不同RPC-API,复杂度提高,增加了开发人员的维护负担,这在当前的业务流量规模下不太可取。所以我们选择了在同一个支付服务API内部进行渠道隔离。由于共用同一个支付服务服务API连接池,渠道隔离的首要目标就是避免故障渠道大量占用AP连接池,对其他正常渠道造成株连影响。如果能够自动检测出故障渠道,并在其发生故障的初期阶段就快速失败该故障渠道的请求,则从业务逻辑上就自动完成了故障渠道的隔离。
  • 隔离到什么程度 一个支付渠道下存在不同的支付方式(信用卡支付、借记卡支付、余额支付等),而有些支付方式(例如信用卡支付)还存在多个银行。所以我们直接将渠道隔离的最小粒度定义到支付渠道 -> 支付方式 -> 银行。

基于上述的思考,我们设计并实现了一个针对故障渠道的快速失败(fail-fast)机制:

  • 将每一笔支付请求所附带的支付信息抽象为一个特定的fail-fast路径,请求抽象成一个fail-fast事务,请求成功即认为事务成功,反之,事务失败。
  • 在fail-fast事务执行过程中,级联有2个fail-fast断路开关:
    • 静态开关,根据人工配置(on/off),断定某个支付请求是否需快速失败。
    • 动态开关,根据历史统计信息,确定当前健康状态,进而断定是否快速失败当前支付请求。
  • 动态断路开关抽象了3种健康状态(closed-放行所有请求;half_open-部分比例的请求放行;open-快速失败所有请求),并依据历史统计信息(总请求量/请求失败量/请求异常量/请求超时量),在其内部维护了一个健康状态变迁的状态机。状态变迁如图4。
  • 状态机的每一次状态变迁都会产生一个健康状态事件,收银台服务可以监听这个健康状态事件,实现支付渠道的联动上下线切换。
  • 每一笔支付请求结束后都会动态更新历史统计信息。

经过线上流量模拟压测观察,fail-fast机制给系统支付请求增加了1~5ms的额外耗时,相比第三方渠道的支付接口耗时,占比1%~2%,属于可控范围。渠道故障fail-fast机制上线之后,结合压测配置,经过几次微调,稳定了线上环境的fail-fast配置参数。

在前不久的某渠道支付故障时,通过公司内部的监控平台,明显观察到fail-fast机制起到很好的故障隔离效果,如下图5。

为解决问题(3)中支付链路可用性监测,依赖公司内部的监控平台上报,实时监控支付成功通知趋势曲线;同时渠道网关系统内部从业务层面自行实现了支付链路端到端的监控。秒级监控支付链路端到端支付成功总量及支付成功率,并基于这2个指标的历史统计信息,提供实时的支付链路邮件或短信报警。而在流量高峰时,该监控还可通过人工手动降级(异步化或关闭)。这在很大程度上提高了开发人员的核心支付链路故障响应速度。

为解决问题(4)中的“绿帽子”,渠道网关系统配合DBA回收所有外部系统的DB直接访问权限,提供替换的API以供外部系统访问,这给后续的提升DB稳定性、DB容量规划以及后续可能的异步多机房部署打下基础。

针对问题(5)中退款case,渠道网关系统配合退款链路上的其他交易、支付系统,从源头上对第三方渠道退款异常case进行统一收集、整理并分类,并形成退款链路核心指标(退款当日成功率/次日成功率/7日成功率)监控,该部分的系统实践会随着后续的“退款链路统一优化”一起进行分享;

随着上述实践的逐步完成,渠道网关系统的可用性得到显著提高,核心链路的API接口可用性达到99.99%,在公司的917大促中,渠道网关系统平稳度过流量高峰,并迎来了新的记录:提交第三方渠道支付请求的TPS达到历史新高。且在部分渠道接口发生故障时,能保证核心支付API接口的稳定性,并做到故障渠道的自动检测、恢复,实现收银台对应渠道的联动上下线切换。同时,通过核心支付链路支付成功率监控,实现第三方渠道内部故障时,渠道上下线的手动切换。至此,基本保证了在部分第三方渠道有损的情况下,渠道网关系统的柔性可用。演化后的此阶段系统架构如图6。

四、经验与总结

在整个渠道网关系统一步步的完善过程中,踩过很多坑,吃过很多教训,几点小的收获:

  1. 坚持核心思想,拆分、解耦,大系统做小,做简单;
  2. 系统总会有出问题的时候,重要的是如何快速定位、恢复、解决问题,这是一个长期而又艰巨的任务;
  3. 高可用性的最大敌人不仅是技术,还是使用技术实现系统的人,如何在业务、系统快速迭代的过程中,保证自我驱动,不掉队;
  1. 高流量,大并发对每一个工程师既是挑战,更是机遇。
转载地址:http://tech.meituan.com/The-Practice-of-Dianping-Channel-Gateway.html

支付渠道网关系统的实践之路相关推荐

  1. 大众点评支付渠道网关系统的实践之路

    业务的快速增长,要求系统在快速迭代的同时,保持很好的扩展性和可用性.其中,交易系统除了满足上述要求之外,还必须保持数据的强一致性.对系统开发人员而言,这既是机遇,也是挑战.本文主要梳理大众点评支付渠道 ...

  2. 支付渠道网关设计2.0版本

    文章目录 支付渠道网关设计2.0版本 前言 概述 业务架构设计 技术分层设计 友情链接 支付渠道网关设计2.0版本 前言 之前写过一篇支付渠道网关设计的文章https://shanglishuai.b ...

  3. 京东10亿级调用量背后的高可用网关系统架构实践!

    http://developer.51cto.com/art/201711/557049.htm "京东开放服务平台是京东对外开发的窗口,每年的 618 大促,京东的网关都要承载十亿级的调用 ...

  4. 支付渠道路由系统进化史

    支付系统一般需要对接多个支付渠道,一是为了保证系统的可靠性,不能因为单一渠道的问题影响整个支付系统.二是为了提高支付能力,不同渠道提供支付能力不同.三是为了降低支付成本. 对接多个支付渠道以后,为了可 ...

  5. 360内部监控系统Wonder实践之路

    女主宣言 Wonder监控系统目前已经是360内部最大.最健全的监控系统.基于open-falcon改造的Wonder,从2016年4月上线至今已经运行了一年多,从最初的"乞丐版" ...

  6. 体育赛事直播系统的实践之路

    谓智慧运动场,就是一套利用互联网科技.软硬件集成,实现体育场地升级的解决方案,它可以运用在篮球等一系列球类运动场中,通过摄像头实时捕捉运动员的技术动作以及跑位影像,可以实现场内屏幕直播以及场外网络直播 ...

  7. 支付系统设计三:渠道网关设计02-客户端报文解析

    文章目录 前言 一.后台配置管理 1.1 渠道配置 1.1.1 渠道基本信息新增 1.1.2 渠道交易类型配置 1.1.3 渠道商户信息配置 1.1.4 账户配置 1.1.5 交易类型机构配置 1.2 ...

  8. 京东千万并发 API 网关实践之路!

    来源:京东零售技术(id:jd-sys) 链接:京东API网关实践之路 概述 1 背景 京东作为电商平台,近几年用户.业务持续增长,访问量持续上升,随着这些业务的发展,API网关应运而生. API网关 ...

  9. 得物从0到1自研客服IM系统的技术实践之路

    本文由得物技术王卫强分享,为了更好的阅读体验,有较多的内容修订和排版优化. 一.引言 客服IM的核心业务其实就是在线沟通,客服IM的好处是使得客服与用户通过实时沟通的方式可以在最短的时间内帮助用户解决 ...

最新文章

  1. 【杂谈】2020年有三AI计算机视觉培养计划详解,该不该学怎么学CV的简单讨论...
  2. 如何用python写脚本_【按键教程】用python写脚本 另附垫材24与变奏22的实现
  3. bom event周期_DOM-BOM-EVENT(1)
  4. J2EE进阶(十五)MyEclipse反向工程实现从数据库反向生成实体类之Hibernate方式[申明:来源于网络]...
  5. JS_理解函数参数按值传递
  6. Linux:查看文件夹大小
  7. Java编程思想学习录(连载之:初始化与清理)
  8. 【备忘】年薪50万2018年最新北风网大数据Spark2.0从入门到精通视频教程
  9. Delphi FireMonkey 3D 编程初探
  10. 应用ruby打造个性化的有道单词本 (一)
  11. 知识图谱+Recorder︱中文知识图谱API与工具、科研机构与算法框架
  12. 搜狗浏览器异常问题 - 解决方案
  13. 乐符识别matlab,基于DPP的自动音符切分识别研究
  14. 2020/1/17用python制作二维码
  15. mysql主从配置duxi_手把手超详细Docker部署MongoDB集群
  16. 电路方案分析(二)BLDC驱动和控制电路原理图分析
  17. python-科研绘图系列(3)-雷达图
  18. 大众点评坐标抓取php,如何抓取(采集)大众点评网的坐标(经纬度)信息
  19. 百大行业翘楚齐聚一堂,浪潮服务器惊艳MWC
  20. php欢迎界面代码,分享微信小程序欢迎界面开发的实例代码

热门文章

  1. Stata:异方差和自相关稳健F检验和t检验
  2. opengl,opengl es,egl,glfw,glew
  3. 浅析DDOS攻击及防御
  4. 宏转录组方法_宏基因组理论教程6宏转录组
  5. php 公众号微信支付流程,微信公众号支付完整流程案例
  6. 我的2011,逝去的只是青春
  7. 一个CTU分割细节过程—— VTM (13.0)源码阅读
  8. 维吉尼亚密码 算法 Java实现
  9. 艾司博讯:拼多多有展现没有成交的原因
  10. 二十八,打糕蒸馍贴花花