消息队列中参数的传递和存储
消息队列(MQ)在系统架构中发挥了重要作用,其主要作用有系统解耦,流量削峰,异步消息存储,分布式系统最终一致性等。 本文介绍的是消息系统中消息发布者和订阅者间参数如何约定和传递?实际应用场景中,一种消息的发布者和订阅者都有可能是多个,也就是多对多的关系,这样就形成了消息参数传递的复杂性,就算一开始参数有约定,大家都按照最初约定来开发,但不免开发过程中各端需求变化带来的修改。例如最开始为了实现系统解耦而引进了消息队列,此时消息参与者较少,只有一个发布者和一个订阅者,这种情况最简单(其实最简单还是直接调接口),双方简单约定了需要传递的参数。
{ userId:123, userName:"阿离", age:23 } 后来订阅方又需要性别,地址,工作等信息,要求发布方加参数,这种要求也不过分,那就加好了。
{ userId:123, userName:"阿离", age:23, gender:"女", address:"上海", job:"测试" } 再后来又有一个订阅者参与进了消息系统,要求在上述参数中再加“工作年限”参数,那么先不说什么了,加呗。
{ userId:123, userName:"阿离", age:23, gender:"女", address:"上海", job:"测试", workingLife:4 } 再后来又有不同的订阅者参与进消息系统,每个订阅者都可能有自己的参数要求,参数类型不同,随着系统的发展,连发布者也有多个。这时最初的文档或约定已经不奏效了,总会有人不能及时更新文档导致约定不能成为约束,各自为政,比如“学历”参数有的人要求叫“硕士”,有人要叫“研究生”,总之是很难统一。如果要继续修改发布参数就会有很多冗余出现,参数类型不统一出现系统故障。
这时消息系统已经不是当初简单的两个发布者订阅者了,而是一群人在参数,所谓的众口难调。此时弊端已现,无论哪一方有变化都势必牵连所有人。所以看出的出这种消息参数传递有其不合理的地方,那么怎么传递更合理?此处的MQ最开始已经说了,是为了解耦而引进,说明该MQ是多个系统的衔接者,而多个系统终究还是系统,不是简单的前端和后端接口调用,例如某个前端A也是由自己的接口提供服务系统的,MQ不是直接为前端A提供参数的。应该是由前端A自己的服务端A订阅消息,前端A需要什么参数就有服务A查询需要的参数即可,前端B需要什么参数由服务B查询提供。而发布者A,发布者B等只需要传递关键参数userId即可,其他姓名,性别,年龄什么的都不需要传。
此时有人喜欢拿性能来说事,觉得应该由发布者一次性查出来传递并(作为日志)存储,订阅者不用每次都查询那么多相同参数,这是没理解MQ的意义,MQ应该是负责告诉其他人发布者做了什么,而不应该由订阅者决定发布者和MQ应该怎么做。因为既然是解耦系统,那么各个系统有不同需求,也可能有自己的数据库,就算是要记录日志也是由各系统自己负责存储,不应该由MQ来存储,如果所有参数都由发布者来查询那是不是会降低发布者的性能?就像上面的情况,MQ的参数随着各端要求不断增减,类型变化,最后存储的参数会变得乱七八糟,根本无法使用。
总结:消息队列应该只传递和存储关键信息,如ID就足够了,如果传递多余信息而造成不一致也会出现扯皮的事。各个订阅方自己负责其他参数查询和日志存储,否则就不是解耦了。