文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

防御性编码的意识与实践

2024-11-30 07:45

关注

在编程领域也有防御性编码(Defensive coding),有着与汽车防御性驾驶相似的理念,它也是保护我们的系统的一种实践,减少线上事故的发生。

一个大型系统必然是多个团队的协作成果,团队之间的接口调用通常靠文档规范约定,这些接口文档也便形成了一份份规约。可能有人会说对方团队不遵守文档规范是对方的问题,不关我们团队的事情啊。对于这个问题,我只想说只关心自己不被追责而不关心技术全局是否完善的技术人员注定发展空间是有限的。因为各类规范只能保证下限,在团队与团队的协作中仅仅按契约完成规范还不够,就像仅按交规开车并不能防止事故一样,我们还需要防御性编码的意识与实践。那怎样做到防御性编码呢?下面是最常见的一些手段:

1、日志记录

作为本系统与外部系统接口交互的记录,必须要记录日志。日志无论在事中查错、事后追责提供证据方面都有着不可替代的作用。如果自己的系统没有日志,就只能寄希望于上游或下游记录了日志,这有时不仅受制于人,还可能会为日后互相甩锅埋下隐患。对于重要的(如涉及资金),或者频繁需要查日志的系统间交互,不仅需要打印应用日志,还需要考虑将这些日志记录到数据库或NoSQL中并提供方便的查询界面以提高查询的效率。

2、协议之外

比如某第三方支付系统的接口规定,调用支付接口后返回报文的支付状态字段,1代表支付成功,0代表支付失败,-1代表不确定。结果线上因为对方升级协议的原因,多了一个状态2,而这个业务的程序员又没足够的经验预判这种情况,引起了大面积的支付错误投诉。他的代码是这样写的:

if(status == -1){
    //支付结果不确定处理
}else if(status == 1){
    //支付结果成功处理
}else{
    //支付结果失败处理
}

可以看到他把新出现的这个状态当成支付失败处理了。对于这种出现了协议之外的值的情况,在业务开始可以拒绝的情况下直接拒绝该请求调用。在不能拒绝的情况下(如本例中用户已经输入支付密码完成支付,不能再拒绝请求调用了)则需要在业务上兼容处理,比如这里可以把这种情况视为支付结果不确定,最后再根据对账取得最终的支付结果是成功还是失败。

3、输入限制

常见的输入类型有整数、小数、字符串等,我们必须检查输入字段是否符合接口文档规定的类型,并限制字段的基本长度。同时也从业务角度去检查字符串是否满足格式,如常见的身份证、邮箱、手机号码等是否满足各自规定的业务格式。

4、输入过滤

比如你提供了一个搜索接口,但你不确定上游会输入一句话还是一篇文章,光靠双方自觉地按接口文档去约束显得既苍白又无力,一刀切停止服务似乎又过于简单粗暴。一个可行的方法是无论上游输入多少,只截取前30个字符去ElasticSearch中查询(接口协议文档中明确约定)。有时候为了自己系统的安全,对于明显超出正常业务范围的字符也会进行过滤,如常见的<>&\r\n等。

5、边界判断

一个常见的问题是只检查了下限没检查上限,比如商品数量数据,通常会做大于0检查,但却很少会去检查上限。比如在Java中当我们使用内置运算符做数学运算时,如果结果超出变量类型表达范围,结果会并不会抛出异常,而计算结果又是不符合预期的。如两个大的正整数相乘,结果可能溢出后变成了负的。这就要求我们对字段的数值范围,业务取值范围进行进行边界判断。

6、接口限流

我们知道,系统之间交互模式有推送与拉取。拉取虽在及时性上不如推送,但它可以根据系统自身的能力量力而为地处理业务,能较好的保护自身。而推送则有可能出现能力不匹配的情况,如果上游推送很快,自己的系统又处理不过来则需要提前做好限流,并确保上游能兼容限流的情况。

7、重复请求处理

如果指望通过一纸规定就能避免调用方重复发起,就能避免被调用方重复处理问题,那就未免显得有点天真了。因为重复可能发生在应用层,也可能发生在框架或其它层,未必就是调用方主观的行为。对重复请求的处理,有些情况可以用幂等处理,除了部分业务本身就是幂等的,其他多数是通过业务惟一索引进行限制实现。需要指出的是有些系统是通过先查询数据库或缓存再判断是否是重复请求的还需要注意原子操作问题。

8、金额单位

要特别小心涉及金额的接口处理。对金额的处理,不同的系统有不同的标准,同样对于1.23元,某互联网公司的支付系统规定以分为单位的整数(如123);某电信系统则规定以厘为单位的整数(如1230);某金融系统又规定是以元为单位的字符串(如1.23)。尤其需要小心对最后一种情况的数值范围判断,涉及到字符串转数字,要小心精度丢失。在Java中涉及小数的计算,多数情况使用BigDecimal。

防御性编码要求我们跳出责任归属的视角系统性地看待全局问题,对可能发生问题的地方提前预防,对事故高发情况提前预判,保护自己系统的同时也保护上下游系统,取得全局最优解而不仅仅是局部最优解。

来源:彭彭架构笔记内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯