赞
踩
2011年11月10日,世纪光棍节前夜,支付宝大楼的一间大型会议室里,数十号人严阵以待。0点刚过,投影在幕布上的交易、支付曲线,几乎成90度直线上升。仅仅几秒钟之后,支付宝大促专用旺旺群开始闪烁:
“【支付宝大促决策-#1】对*行执行渠道限流措施”,
“【支付宝大促决策-#2】对*行网银执行渠道限流措施”,
“【金融渠道决策参数调整-#1】:**银行收银台限流:3QP3M”,
“【金融渠道决策参数调整-#4】:**银行收银台限流:9QPM” ……
在接下来的近24个小时里,这样的决策信息几乎没有间断过。而在另一边的用户,则发现支付困难,在微博上,“**银行网银好卡”,“**网银宕机了吗?”的感慨不绝于耳。
发生了什么?别着急,让我们回过头看看饭店的故事。
一家饭店,客人点餐后有两种选择:1,在吧台前站着排队等候,一直等到食物准备完成,领走餐盘用餐;2,从吧台拿一个号牌,回到座位上等待,期间可以喝喝水、玩玩儿手机,食物准备好后服务员叫号,领走餐盘用餐。相信任何一个明智的客人,都会毫不犹豫的选择第二种方案,因为这种等候方式更为高效。
然而,很多时候,事情却并不像想象的那么简单。
再看整个支付宝系统,他呈现一种SOA(service-oriented architecture)化的架构,它不是单一的,是由成百上千个子系统之间以“服务”的方式构成的,比如:交易子系统、支付子系统等,这些子系统互相协作,最终向外界提供完整的支付功能。
就像饭店一样,提供就餐,这就是一种“服务”;顾客在餐馆吃饭,这就是一种“服务调用”。类似的,餐馆为了制作餐品,需要获得食物原料,即需要食品供应商的服务;而提供食品原料的供应商,又需要菜农提供服务。如此一来,就形成了一条服务链:
顾客 —> 餐馆 —> 食品供应商 —> 菜农
在这条链上,每一个提供服务的节点都有两种服务方式可供选择,正如前文所述的那家餐馆,这两种方式是:1,被服务者提交服务请求后,等候,直到服务者准备完成并给出服务结果,这种方式,称为“同步“;2,被服务者提交服务请求后,服务者接受请求并向被服务者提供一个凭证,此时被服务者可以离开,服务者准备完成后,根据之前的凭证把服务结果推送给被服务者,这种方式,称之为”异步“。
套用这个定义就可以发现,如果上面这条链中的每个节点都是同步的,那么整条链完成服务的时间,将由链中最缓慢的一环决定,也就是说位于链条最顶端的顾客,为了吃一顿饭,要从菜农播种开始等待,一直等到菜农收获、食品供应商收购食品并简单加工、卖给餐馆、完成烹饪后,才能拿到餐品,这期间,这名顾客必须站在餐馆的吧台前等着,什么也不能做。
在支付宝各子系统之间,也存在着这样的服务链,比如,一笔支付业务的服务链类似这样:
用户 —> Web收银台子系统 —> 支付子系统 —> 银行网关子系统 —> 银行
这条链上的每一个服务节点都是同步的,是的,同步。也就是说,用户想要完成一笔支付,必须要等待链上的所有支付宝子系统以及银行完成操作。大多数支付宝子系统的业务处理都是非常快的,通常在100个毫秒以下,然而银行,作为支付宝的下游服务者,却不一定能保证速度了。实际上速度并不是银行最大的瓶颈,即使很慢的银行系统,个位数秒内也能完成业务处理,银行真正的限制点在于“并发“。
并发,是指一个系统同时能够处理的业务笔数,可以类比超市的收银窗口,如果有10个窗口,那同时可以有10个人一起付钱,第11个及以后的人就只能排队等候。
支付宝目前已经接入的众多银行中,有不少家其系统性能只能支持个位数并发,不乏有仅支持2-3个并发的银行系统。这就是说若有100个持有该银行账户的用户同时请求支付,最多只允许3个获得服务,其余97个必须被挡在门外,否则超过限制约30倍的流量一涌而下,银行系统很可能被直接冲垮,且在短时间内无法恢复。
为了最大化保证用户能够支付成功,支付宝是不希望任何一家银行被冲垮的,因为这意味着失去拥有该行账户的所有用户。所以,为了保护银行,支付宝必须对下泄给银行的支付请求执行限流。
限流,让同步化的业务模式立刻显现了它的弊端,由于服务链中的每一环节都必须等待后续节点处理完成,整条链就像一根钢筋一样僵硬,完全没有伸缩性可言。为了限制流向银行的请求数目,达到保护银行的目的,必须从链条的顶端就开始限制。
于是,在类似双11这样的大促活动中,大量支付宝用户在提交支付请求的页面上看到一个刺眼的红叉。因为同步业务模式的制约,为帮银行把超出限制的支付请求挡在门外,支付宝,也不得不把它们挡在自己的门外。这是个无奈之举,更为无奈的时,大促时的业务流量具有高峰低谷的特性,可能某一秒钟的前半秒流量还很高,后半秒又瞬间回落,为了能在保护银行的前提下最大化利用银行性能,支付宝系统必须不断调整对各银行的限流参数,这就是文章开头的一幕。
异步化,是解决这种困境的妙药,在支付宝架构层面,这从来都是共识性的结论。
然而,要把一个复杂的互联网应用系统改造为异步化,并不像改变餐馆等餐方式那么简单。这不仅仅是技术上的改变,其中涉及编程方式、开发测试调试方法的改变自不必说,更为困难的是业务规则的改变。仍以之前的支付业务为例,同步模式下,用户通过web收银台向支付宝提交了支付请求后,虽然要一直等待,但只要完成后用户就可以确切的知道自己的支付是成功的还是失败的。
一旦这个过程异步化了,用户点击支付后,确实不用等了,但是这笔支付请求是不是真的被受理了,会不会由于网络上的一些异常而丢失?用户如何知道支付的结果?仅仅是这2个问题,就让这个业务的异步化举步维艰,必须要从技术手段和业务模式两个方面上一起改造,双管齐下,才有可能完成这个任务。
做,难;不做,慢慢被拖死。所以,不得不做。幸好一团乱麻中尚有迹可循:不要求在异步化调用链上每一个节点,而只在关键点上实施异步化;适当改造业务,用轮询等方式在上游模拟同步。
2012年,支付宝启动三代架构规划,第三代架构中把业务异步化作为一个重要的目标。伴随着三代架构东风,支付宝研发了Zqueue(Zhifubao Queue)子系统。Zqueue是一个分布式异步队列组件,应用在理论上可异步化的业务场景中,旨在让这些业务实际具有异步处理能力,Zqueue的首个应用场景,就是前文中的支付业务。
Zqueue就像一个巨大的蓄水池,它架在支付宝web收银台和支付子系统之间,当用户在web收银台上请求支付时,收银台会把支付请求丢进Zqueue中,然后立刻向用户返回,而不再需要等待后续的处理,这实际上就是异步化;Zqueue将池中的支付请求向后面的支付子系统派发,支付系统完成原同步链中后续的操作。应用了Zqueue后的支付业务服务链变成了这样:
用户 —> web收银台 – - -> Zqueue – - -> 支付子系统 —> 银行网关 —> 银行
虚线代表着异步的服务调用,它意味着调用链这个节点上有了弹性,有了伸缩能力,不再是僵硬的钢筋。
一年之后的2012年的双11期间,支付宝完成了超过1亿笔的支付,用户的银行卡类支付成功率同比提升了8%,不要小看这8%,在亿级的支付基数下,8%意味着近千万用户成功的完成了支付,没有被银行拒绝。
这依赖于支付宝整体系统性能的提升,以及银行更加重视网络支付。其中,支付业务的异步化功不可没,使用蓄水池实现的异步化业务具有天生的削峰填谷能力,2012大促全天,支付宝调整银行限流参数的决策不超过10条。
“这是我的一小步,却是人类的一大步”,1969年阿姆斯特朗代表人类第一次踩在月球上时,说出了这句名言。这对于Zqueue系统也同样适用,作为支付宝上千子系统中的之一,Zqueue只是支付宝发展的一小步,然而,这一小步对于支付行业有着并不小的意义。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。