目前碰到一个需求,serviceA 向外发送数据,走完前调用 serviceB 开启一条支线程去重复持续获取操作结果,直到获取结果为止,然后更新 serviceA 的数据状态。 这样导致了 serviceA 调用 serviceB ,然后 serviceB 又要调用 serviceA ,造成了循环调用。 求问各位大佬有什么办法优化一下,另外有多线程和设计模式的书推荐一下嘛?谢谢!
1
xiaohundun 2023-03-24 14:26:52 +08:00
这种为啥不用发布订阅或者基于事件的方式?
|
2
shinyruo2020 2023-03-24 14:35:01 +08:00
这不就是回调吗,serviceA 传一个 Function 给 serviceB
|
3
liudaolunhuibl 2023-03-24 14:37:39 +08:00
1 、你要解耦的话,就重新写一个 serviceC 来获取 A 的数据,serviceA 可以叫 producrService serviceC 就是 consumer Service ,A 负责发数据和写数据,C 负责读取查询,这样 A 发送完数据,调用 B ,B 调用 C 去查询数据,可以理解为读写分离
2 、重复持续获取就是轮询吧 ,轮询不是非常的优雅,因为长时间的轮训会给 CPU 造成压力,最好是按照一楼说的基于事件驱动,也就是操作结果完成之后调用 B ,可以用 MQ 或者单节点就用谷歌的 eventBUs 或者 spring event 3 、多线程和设计模式的书网上一搜一大把 |
4
yazinnnn 2023-03-24 14:51:18 +08:00
你用的啥客户端, 异步却不支持设置回调?
client .send(xxx) .onSuccess(result-> handle(result)) .onFailure(error->handle(error)) 这种形式的代码都不支持码? |
5
litchinn 2023-03-24 15:08:14 +08:00
事件驱动
serviceA 里发布事件,eventA.send() serviceB 作为一个 eventA 的监听器,执行完任务后再发送 eventB serviceA 里再包含一个 eventB 的监听器,监听到 B 事件后更新数据 eventA 和 eventB 可以是同一个事件具有不同的状态,也可以是多个事件,看你的业务进行设计 单体服务用多线程就可以了,分布式集群的话用 mq ,如 3 楼所说的方案 |
6
cencoroll OP @liudaolunhuibl
@xiaohundun @litchinn 非常感谢,大概找到方向了,我研究一下。 @shinyruo2020 回调不太符合需求,但也感谢解答 @yazinnnn 程序其实是操作工控设备,将参数 A 下发以后,等待执行完毕后获取结果。但是这个等待的时长不确定,而且这个结果只需要更新到数据库就行,除非程序遇到情况报错了,否则前端不太需要查看执行结果。 |
7
nothingistrue 2023-03-24 16:24:00 +08:00
如果把 serviceA 、serviceB 看成两个独立的微服务,那么这就不是互相调用,是分布式事件流,虽然看起来比较乱,但是并没有耦合,因为每个 service 都是自成一体,仅通过接口跟外部沟通的。
不过你这个还是有点耦合,需要稍微拆解一下。改成如下过程: -> A 在队列( A 让 B 处理)当中发送一条任务 -> B 从队列收到任务后,执行,得出结果后,在另一个队列( B 返回结果给 A )上,发送处理结果 -> A 从队列收到结果后,执行后续处理(更新数据状态、向外发送等)。 注意一点:如果 A 之前还有调用者,那么 A 是无法向调用者返回最终执行结果的,因为 A 在第一个过程就必须终止同步处理,后面的全是异步的。 |
8
zhuisui 2023-03-24 17:08:17 +08:00
解耦的关键是消除业务循环依赖关系,从来都不是程序的依赖关系。
不管是程序内部的回调函数,还是程序外部的 rpc 或消息队列,或者是什么别的调用形式。 A 委托 B 做一件事,那么 A 就要负责主动接受处理结果。 几种调用方式上,提供回调明示了这个意图,其他异步方式较为隐晦。如果是 rpc ,应该 B 提供 rpc 给 A 进行委托处理和获取结果。如果是消息队列,应该由 B 声明两种工作的消息通道和内容。 总结来说,就是 B 不知道 A 。 |
9
winglight2016 2023-03-24 17:22:10 +08:00
工控设备居然用 java 操作?一般不是用串口线走 mobus 协议,只管轮询 /更新数据区这种方式吗?
想模拟这种方式的话,用 redis 充当数据区就可以了 |
10
Pony69 2023-03-24 17:51:42 +08:00
mq 或者 redis 队列
|
11
urnoob 2023-03-24 18:33:48 +08:00
AB 是
两个 jvm ,没问题啊(又不是不能用) 两个类的 instance 合二为一 抽到 C 学多线程,避免 hang 在那 学多线程知识,避免 hang 在那里 |
12
cencoroll OP @winglight2016 这边大部分都是网口,西门子或是三菱的,直接通过 ip 地址读写数据块的信息。
|