1、分布式程序调用到底是返回错误码还是返回错误信息
分布式系统环境里面,RPC往往被我们称为:连接各个服务之间的纽带。当然,也有MQ。如果纽带这个词显得高雅,通俗点就是信息交互,或者通信。
好,还是说RPC。
现如今,市面上有很多RPC框架,它所要解决的本质问题就是A系统能够和B系统通信,还有智能化些的服务自动发现作为基础。我们现在主要关注A能够调用B,如果B程序出现错误了是返回异常还是错误码。
这其实是一个“争议”不断的问题,我相信你在自己团队内部也曾有过这样的讨论。
现在,虽然A和B两个系统是跨进程了,但仔细想想,对于A系统里面的调用逻辑,在A系统内部实际上就跟同一个进程内处理一样,RPC框架把跨进程通信掩埋了。
那是不是说,我就可以参照单进程内调用方法出错的时候的处理方式一样了。
那是啥样的呢。
翻阅《代码整洁之道》第7章错误处理,7.1章节题目是:使用异常而非错误码。
TIP:为什么要查看这本书,其实都说了实际过程中有不停的讨论,那就看看“权威”怎么说的。当然,你也会抱有“尽信书不如无书”的姿态,但那是在你的发现能“理”过书中的发现的情况下。
如果用错误码,程序会完全由错误处理所占据。
所谓占据,并不是说错误处理就是全部。我的意思是几乎无法看明白代码所做的事,因为到处都是凌乱的错误处理代码。
“错误处理很重要,但如果它搞乱了代码逻辑,就是错误的做法”
这是书中的建议。
怎么个占据法,又怎么个乱法,书中也给了个例子。
也就是异常的逻辑和正常的逻辑混在了一起。
如果采用异常,就可以将异常的逻辑和正常的逻辑处理分离开来,这样代码的可读性就会更好。
这里有人会纠结错误栈影响性能,直接可以告诉你,单进程环境下可以忽略。
在没有实际数据指标的基础上,为了一点点的性能提升而牺牲掉可读性和可维护性是得不偿失的。
这是单进程代码环境下的情况,处于分布式环境下,系统在跨进程的调用的时候可以这样做吗?
带着问题,继续找“权威”做参考。
参考大量的实践经验就好了,哪里有大量的实践经验,经验的载体形式又是什么样的呢,很快能想到的是流传江湖已久的《阿里巴巴Java开发手册》。
我们看到,“跨应用间RPC调用优先考虑使用Result方式,封装isSuccess()方法、错误码、错误简短信息”,为什么不建议直接返回异常信息了呢。下面也给出了解释,“如果加了栈信息,在频繁调用出错的情况下,数据序列化和传输的性能损坏也是问题”。
那么现在你就有了一个自己的参考了,单进程内,跨进程间,这两个环境下,具体是返回错误码还是返回错误信息,相信你已经有答案了。
TIP:注意,这份开发手册,关于12是标注为【参考】,熟悉这份开发手册的朋友,都知道还有个【强制】,那这里关于抛异常还是返回码,为什么不是强制而是参考呢。是需要分具体来看的,我举个例子,如果明知道调用量不大的情况下,对性能也在可承受返回内的情况,是不是就有不一样的做法了呢。
2、我作为一个负载均衡,我最大的苦恼是什么
如果我是一个负载均衡,我最大的苦恼一定是有个叫做“状态”的东西萦绕我。
负载均衡,不就是把客户端的请求送到后端服务上去么,第一次请求、第二次请求等等,后续不论来了多少请求,我都可以随意略带任性的发往任意一个后端服务。
可是,一旦有了状态,我就要考虑这一次请求和上一次请求之间的”信息连接点“,还在不在,还在不在这一次请求所抵达的服务器上。
问题1:什么是分布式系统的状态?
分布式系统环境里面,应对这样的状态的时候,我们一般都是把这些状态数据抛到远程存储中心里面去。
有的时候,我们为了提升访问性能,又在后端服务所在的服务器上面按照某个规则存储一份数据,比如,按照用户ID来缓存用户信息。这样,确实解决了分布式状态的问题,“专职的设备干专职的事情”。
这样一来呢,多少有点小麻烦。
随着不同用户访问量的增加,在缓存失效的时间窗口内,每个后端服务上做存储的数据会越来越多。
这个时候,有人就提出来了:如果我们能将同一个用户的多个请求,都发送到同一个实例上面去,不就不用缓存那么多数据了吗。
确实,这个是负载均衡里面的一种,叫做状态负载,更多的路由算法内容,大家可以搜索一致性Hash算法来了解。
但是,仔细想下,真的会耗费那么多本机内存吗。如果是“猛一想太多,实际一分析还好”,那我们就大可不必费劲地使用状态负载了,负载有了状态终归是件麻烦事。
当然,对于负载均衡,你如果硬要这样做,就想搞一个状态负载,也不是不可能,下面就是一种方法。
全状态的负载均衡一般以路由服务的形式存在,在路由服务里面,都会存储后端实例 ID 和状态信息的索引,在进行请求路由的时候,路由服务从请求的状态信息中获得索引的标识,通过查询索引获得后端实例的 ID,然后再进行路由。
有些存储的集群就是这么做的,比如Redis的分片,或者说大部分数据存储的数据分片都是这样的原理。
3、你认为分布式系统的缺点都有哪些
架构设计变得复杂(尤其是其中的分布式事务)。
部署单个服务会比较快,但是如果一次部署需要多个服务,流程会变得复杂。
系统的吞吐量会变大,但是响应时间会变长。
运维复杂度会因为服务变多而变得很复杂。
架构复杂导致学习曲线变大。
测试和查错的复杂度增大。
技术多元化,这会带来维护和运维的复杂度。
管理分布式系统中的服务和调度变得困难和复杂。
--《左耳听风》
4、你有么有想过,为什么设计模式分为了创建型、结构型、行为型
因为,对象就是在干这三样事情,做创建、做结构、做行为。设计模式内涵是将多态的灵活应用,通过创建、结构、行为给“活现”出来,给我们一个立体的参考指引。
设计模式的精髓在于对面向对象编程特性之一——多态的灵活应用,而多态正是面向对象编程的本质所在。
----END----
这里记录,我每周碰到的,或想到的,引起触动,或感动的,事物的思考及笔记。不见得都对,但开始思考记录总是好的。