ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

【项目经验】实现一个对外调用功能

2021-05-21 13:29:34  阅读:180  来源: 互联网

标签:返回 经验 请求 结果 rpc 调用 超时 对外


业务场景:

开发一个模块,接收rpc计算请求,转发请求给外部,然后同步返回结果给调用方。本地调用是同步的,外部调用是异步的。

 

设计:调用方C(lient,客户端),本模块S(erver,服务端),外部接口应用 E(xternal,外部)

  • 向C提供接口直接本地调用,功能分C端接口,和S端实现,mq作为协议层
  • 目前架构:后端所有模块采用rabbitMQ异步通信。在不引入新 组件的前提下,只能用mq模拟rpc。
    • =》mq是支持RPC的,但由于项目架构所限,不能直接使用源生的rpc接口,参考源生实现:发送信息中附带请求ID和结果接收队列,在业务层模拟rpc。不管任何节点收到结果,都可以根据队列名放入同一队列,调用方就能从该队列拿到返回的结果。但是要求一点:一个调用方节点对应一个队列
  • 既然是rpc调用,C请求S应该是同步的,S在转发请求给 E 后收到结果之前,应该是阻塞的;而且S向E的请求线程Req和S接收返回的线程Resp是两条线程,且结果从Req返回,怎么将结果从Resp传给Req呢;而且不能一直阻塞,需要有一个超时时间
    • =》联想到Futrue接口,查看实现,里面有个jdk8提供了CompletableFuture,看着名字感觉蛮符合我的要求的,查看方法,<T> T  get(timeout,timeUnit),complete(T t),调用get阻塞,等待timeout超时,或者直到compelete返回结果,满足需求。
  • 考虑到接口的结果返回形式可能是组播(任选节点返回)或群播(推送给所有节点),计算节点需要支持分布式,也就是节点S1收到C的请求,节点S2如果收到结果也能返回给C。且返回的结果要求填入请求报文的部分字段
    • =》初步设计,S1收到请求后,将请求缓存到redis,供S2处理结果时使用
  • 需要支持批量计算,但接口不支持,只能逐个调用:
    • =》请求一次性发出,用哈希表,REQ+C的请求ID 作为key,缓存所有 请求ID到请求报文的映射 到redis,并另外用集合,RESULT+C的请求ID作为key,存放结果,等结果数量=请求数量时,返回;或者直到超时,返回部分结果
  • 部分请求是失败的情况下,会造成返回两次,超时返回和正常返回,只能返回一个
    • =》首先考虑下,并发问题,超时返回和正常返回一起返回会影响结果,要加分布式锁,请求id做key,节点ID做value,设置超时时间。在超时或者正常返回后,清空缓存,缓存中没有数据,就不执行超时或者返回逻辑。

出现问题:

和架构设计冲突,架构基于事件驱动,每次收到事件,分配一个线程进行处理。如果请求事件Req分配给A线程,阻塞等待结果;收到结果Resp后,又分配给A线程,则造成伪死锁,请求必定超时,且在超时后打印日志,“开始处理结果”。由于分配是根据hash码随机分配的,并不能保证请求和返回事件不会分配给同一事件

解决思路 =》关键是请求和返回的事件不能分配给同一线程处理

  1. 请求事件,另起一线程处理 =》 不行,rpc的请求线程必须阻塞
  2. 返回事件,另起一线程处理 =》需要弃用架构,并自行mq的消费逻辑,该实现需放在C端接口jar中,导致C应用本身不能再添加自身逻辑(可以理解为一个mq消费实现一个bean,这个bean由mq实例调用,要么调用计算功能实现的bean,要么调用应用本身实现的bean,这是冲突的)。或者再加一个mq实例,都不太可取。
  3. 弃用MQ模拟rpc的方式,引入rpc组件,解决

引入rpc组件后,产生新的问题:原先是支持分布式的,而rpc组件要求,请求给S1,结果就也得S1处理,如果S2处理,已经没有队列可以放了

  • =》接口组播的情况:S2收到结果,判断是否是自身的请求结果,是则返回,不是则广播出去。S1收到广播,返回结果。其他S3,S4等节点收到广播,不处理,只有在收到的消息是组播且消息不是自己的,才广播。否则如果只判断不是自己的就广播,会造成无限广播的情况。
  • =》接口广播的情况:不是自身的请求结果,丢弃,不处理。

总结:

问题的产生是,因为mq模拟rpc实现与架构设计的冲突。另外,接口只支持单个计算请求,和返回结果的方式可能是组播或者群播,这两个设计的不合理,导致增加了很多工作量。

标签:返回,经验,请求,结果,rpc,调用,超时,对外
来源: https://blog.csdn.net/u014542626/article/details/117115592

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有