平安某金所电面后不禁想问,是他奇葩还是小弟我奇葩?-关于幂等和ROA设计的反思

平安某金所电面后不禁想问,是他奇葩还是我奇葩?-关于幂等和ROA设计的反思
     在公司一直在做跟支付有关的项目,某日接到平安某金所一男子电话,应该是之前某猎头投的,我正好在吃早饭(也不能怪他们上班早,我们公司弹性工作制,我一般上班比较晚)。

      因为饭馆信号不好,只能赶紧放下剩下的半碗馄饨(肉痛啊),走了一公里(那片移动信号真是渣)。

      终于可以正常交流了。对方让我先挑一个项目说说,我一听这套路,牛啊!跟之前的阿里一样(以后找机会再聊聊那次面经),肯定是随机在我项目中找点来问了,那我就开始说,说到有个补扣款的场景,一开始设计每次客户端发差额过来,很难保证幂等性,后来设计让客户端发总额过来,幂等问题解决了。这里我重申下幂等定义啊,想必大家都知道了,就是对于一个操作,多次执行,副作用是一样的,而不是叠加的。比如我扣款,如果我无法分清客户端过来的差额是补扣还是重试,那么很可能多扣客人钱。

      那么问题来了,总额模式为什么能解决问题?某金所面试官逮到机会发问,而且我注意到他的发问仿佛是循循善诱,告诉我,年轻人,你是不是不懂幂等啊,跟我这里乱讲,我知道的解决幂等的方案是不一样的喔!我当时没反应过来,觉得大牛应该不用我解释幂等吧,应该是在考校我,那么我就描述了一下场景,如果保险费原来是10元,客户端增加了10元,加一加,20元给我,那么即使这个20元给了多次,保险费还是20元不会变,是不是这个理?

      然后奇葩的事情发生了,面试官开启教育模式,后面就一直是他在说,说我这个只是业务上的变动而已,并没有真正的解决幂等啊(我心想这怎么没解决幂等呢,从定义上来说解决了啊),然后又说,差额也能解决幂等问题啊,我就可以解决!我赶紧说,我也可以,就是用唯一的UUID策略,重发的话使用上次同样的UUID,那么我这边服务就不做处理落。他说,你知道为什么不说呢,这个才是技术上的正解啊,你跟我说业务上的东西干嘛啊,你说的根本解决不了问题,还是要用这方案才行。我说,这个是基础的东西,类似接口实现都会那么做啊,但是由于是老的协议,这个临时方案改动最小,也最经济。然后面试官沉默了一会儿,问我,你说说你在Java方面的心得吧,我说了一点,但是明显感觉他在敷衍了。后来就没有后来了。

      说真的,这次面经真是让我深受打击,面试官到底是大牛呢,还是只知道背书的奇葩呢?但是,正是因为人家是平安某金所的总监(也许吧),我只是渣渣程序员一枚,这种地位差距导致了我对自己知识和经验的怀疑。

      但是最近看到了大神Jim Webber的大作REST in Practice,我重新找回了自信心,其中介绍到HTTP的PUT方法是幂等的,为什么呢,解释是这样的(我直接打中文了),“由于PUT请求是幂等的(因为服务端状态被客户端状态整个地替代了),消费者可以安全地按照自己的需要多次重复该操作......”。

      这里大神提到的其实是一种面向资源的设计理念(ROA),PUT方法实现对资源的更新,就像保险费,如果你把它看成是资源,那么每次就应该直接用新值替换(总额替代总额),而如果你把修改保险费本身看成一种操作,每次需要扣多少钱(总额减差额),那么就会破坏幂等,而我们现在大多WebService的设计都是基于操作的思维,为了实现幂等又引入一套复杂的机制,人为添加了复杂性。
1 楼 易水寒vn 7 小时前  
也许我没看懂?!你那20元是客户端直接丢给你的?
那你有没有考虑过安全问题?网络是不安全的,你服务器接受到的数据完全可能是假的。
而使用uuid方式,虽然依然存在安全风险,但是相较与直接接受总额来说,更安全一些,而且可以针对uuid做一些不可逆的加密验证操作,增加安全性

我们现在大多WebService的设计都是基于操作的思维,为了实现幂等又引入一套复杂的机制,人为添加了复杂性。

很多时候是为了安全性,才增加的复杂性,不是那么简单的
2 楼 jingzhongwen 4 小时前  
易水寒vn 写道
也许我没看懂?!你那20元是客户端直接丢给你的?
那你有没有考虑过安全问题?网络是不安全的,你服务器接受到的数据完全可能是假的。
而使用uuid方式,虽然依然存在安全风险,但是相较与直接接受总额来说,更安全一些,而且可以针对uuid做一些不可逆的加密验证操作,增加安全性

我们现在大多WebService的设计都是基于操作的思维,为了实现幂等又引入一套复杂的机制,人为添加了复杂性。

很多时候是为了安全性,才增加的复杂性,不是那么简单的

1.安全的话,整个报文体就是加密的,uuid作为幂等验证需要是在解密前快速对比,所以是没必要加密的
2.面向资源的更新替换操作是天然幂等的,所以不需要额外机制来保证幂等
3.你说得很对,安全问题确实是不简单的,尤其是支付类,不但要防止fake,还要防止泄露,所以需要对整个报文进行不可逆加密,同时有soa治理平台提供白名单策略,如果是webapi还需要引入oath和https,这里面涉及很多