exception和error的区别?

他们2个都是Throwable的子类。

error是程序没有办法处理的异常,常见的有OutOfMemoryError,StackOverflowError,内存溢出了,你代码怎么处理这些异常? 打印一行错误日志吗?或者JDK给你提供了方法让你能把内存释放掉? 就算给你提供了,那你知道要释放哪些内存呢?显然都不是合理的解决方案。那你代码还不如不处理这种异常。当内存溢出了,我们通过监控等手段发现内存占用量高,然后在去定位问题。

exception是程序能够处理的异常。 但是需要注意的是catch里面的处理逻辑。实际很多场景并不是简单的打印一行错误日志这么简单的操作。

比如写接口,程序在运行完主流程后,往数据库写入一条操作日志,这个操作日志又不影响主流程,我们就可以把这个insert try

catch住,insert出现问题了,我们可以发送一条MQ消息,MQ消息有重试机制,确保insert操作成功。或者我们可以把失败的数据保存到MySQL异常处理表中,然后运行定时任务,将运行失败的数据同步到对应的业务表中。

读接口,比如c端的一些交互接口,我们不仅要catch住,还要返回一些兜底数据。

比如查询商品列表,当调取商品信息接口查询商品详情异常的时候,我们可以返回一些兜底的商品数据,这些商品数据可以写死或者将这部分商品信息维护到动态配置中心里面;

接下来看一下具体的业务应该怎么样处理异常。

读接口异常处理方式:

先看一下业务背景:

这个是商品详情页:包含商品详情数据和评价数据;首先用户只有看到商品了才能下单,评价信息只是辅助用户下单,那么当查询商品信息出现问题,系统必须异常,如果仅仅是评价信息查询异常;那页面最多不展示评价信息就好,因为这个不影响用户下单;(但是评价系统也要保证服务稳定性的,毕竟是c端交互的接口)

看一下代码,代码的逻辑也比较简单。先查询商品数据,然后查询这个商品的评价数据,最后拼接数据,返回。

问题:

如果查询商品评价信息接口异常了,那么我们整个接口都要发生异常。商品数据是用户下单必须要展示的数据,评价数据只是辅助用户下单的。那为什么查询评价数据异常了要影响商品详情页的页面数据展示呢?

我们将代码改成如下形式:

将查询评价信息的逻辑try{} catch住,当查询评价数据异常后,我们的页面降级,不在展示商品评价信息。 不是评价数据不重要,只是我们为了维护系统的稳定性,不能让评价数据影响到整个商品详情的页面展示。

看另一个场景: 查询商品列表的页面,当查询商品列表出现异常了,这个页面出现系统异常或者会出现空白页

有没有更好的办法,当查询商品列表数据异常了,我们给用户返回一些兜底数据,让这个页面不出现空白,就是系统异常了,也不让用户感知到。查询出来1-2条数据和出现空白是2个概念

看一下代码:

分页查询商品数据。当查询商品列表异常时,如果是第一页数据我们可以返回兜底数据

问题:

我们将兜底数据写死了,返回的是name为商品的数据。 如果以后运营或者产品想将兜底商品改成商品1,我们后端需要修改代码然后发布上线。有没有一个更好的办法,让我们不用上线就可以修改这个兜底数据的。 就是动态配置中心,我们可以将兜底数据放到动态配置中心里面,当数据需要修改的时候,修改配置中心的数据就好

写接口异常处理方式:

看一下业务背景: 用户点击提交订单,流量到达订单系统,订单系统保存订单数据。

看一下代码:

代码逻辑是保存订单数据,然后插入数据到操作日志表里面。

代码这么写有什么问题?

用户下单,最重要的是保存订单数据,保存完订单数据后,插入操作日志异常,那么整个服务异常,用户下单失败。 保存订单数据是主流程,保存操作日志数据是非主流程,为什么要让非主流程的代码逻辑影响到主流程的稳定性?

将代码改成如下形式。将保存操作日志的数据try{} catch{}住,这样即使保存操作日志数据异常了,服务也不会异常。

问题:

系统异常后,我们将订单日志数据直接丢了。如果客服系统的订单数据来源是操作日志表那? 用户下了单,过了一段时间,发现自己的订单有问题,打客服电话,客服通过客服系统去查询这个订单数据,客服系统的数据来源于订单日志表,现在这个数据丢掉了,那么客服怎么样解答用户的问题?解决保存订单接口的稳定性同时引入了其他bug。

我们需要将代码改成如下形式:

保存订单操作日志的接口我们仍然try{} catch{}住,当出现异常的时候,我们可以发送一条MQ消息,这个MQ消息里面包含订单日志数据,用MQ消息的重试机制确保数据保存到订单日志表里面。 或者我们可以将订单日志数据写入到其他表里面,用定时任务去轮询这张表里面的数据,将异常的数据保存到订单日志表里面。这个就是当写入数据异常后我们可以用mq或者定时任务将数据补偿。

总结:

1.error异常不需要抓取,抓取了你也没有合适的办法处理这部分异常;

2.exception异常不同的业务有不同的处理办法;

你的业务如果只是简单的B端或者运营端业务,很多场景你都不需要处理异常,甚至都不需要catch;

你的业务如果是c端或者是b端的一些核心接口;

读接口:

1.先确定哪些数据是必须要返回的。比如商品详情页,商品数据是必须要返回的,如果商品数据都没有,那用户怎么样下单?而商品的评价数据,不是这个数据不重要,只是你已经知道查询评价数据异常了,但是商品数据查询到了,为了不影响用户下单,那就降级,不展示评价数据。

2.这个接口如果没有查询到数据是否要返回一些兜底数据。比如商品列表不能返回空白页,这个时候你就需要返回兜底数据。这个兜底数据你写死或者放到动态配置中心里面都可以,但是最好放到动态配置中心里面。

写接口:

先确定业务的核心链路是什么,非核心链路是什么。非核心链路的稳定性是否影响到了核心链路。

如果你的服务是订单系统,对于用户下单接口,最重要的就是保存用户的下单数据(核心链路),其他数据异常了(非核心链路),不是这些数据不重要而是这些数据的异常不能影响用户下单,后期可以再去补偿这些数据,可以用MQ或者定时任务去补偿这部分数据。

#技术##面试题目#
全部评论

相关推荐

头像 会员标识
03-28 21:35
已编辑
浙江大学 Java
#牛客AI配图神器#1. HashMap底层原理,什么时候转链表,什么时候转红黑树2. HashMap线程安全吗?ConcurrentHashMap和HashTable底层怎么实现线程安全的3. 实现线程安全的方式还有哪些,除了锁?sychronized和reetrantlock的区别4. volatile底层是怎么实现的5. ThreadLocal底层原理6. ThreadLocal使用会不会有一些问题?怎么解决7. 你项目哪些地方用了缓存,Redis缓存是怎么实现的(但是居然没问缓存三剑客,感觉下次是不是得主动多说一点)8. 你这个缓存有没有预热9. Redis分布式锁的实现10. Redis分布式锁会不会有问题11. 使用 Redis + Lua 脚本实现对用户秒杀资格的预检是怎么做的,CAS解释12. 你这个对Redis的操作是怎么实现的,是硬编码的吗,还是使用jdbc?(这个问题稍微没有理解,后来再问了下是不是想问Mybatis,面试官说是的,问我是不是通过注解实现的)13. 点评为什么用session登录,并表示session登录比较老,为啥不用jwt之类的。Session共享问题14. jwt是怎么做校验的15. jwt的payload里面存了什么信息16. MySQL的索引类型?什么情况下索引会失效17. 最近有学习什么新技术(哽住,最近都在复习,开始往自己最近背的知识点扯)18. 你有使用什么AI工具19. 遇到技术方案有分歧怎么解决20. 作为♀为什么会想做开发,这个比产品加班多(emmm)反问:负责的业务、结合AI的内容、他们在用的AI工具、数据安全问题,以及交流发现虽然业务会接入大模型,但是面试官说基本不太会去关注大模型相关的东西(是的,他甚至都没发现有论文那一行),主要还是看开发相关的项目总结:确实存在一些问题不知道如何表达or不知道往哪些点去答,业务细节+底层要多熟悉,优化一下项目吧
点赞 评论 收藏
分享
评论
1
2
分享

创作者周榜

更多
牛客网
牛客企业服务