V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
xxxyangyu
V2EX  ›  程序员

如何保证控制消息可靠?

  •  
  •   xxxyangyu · 2023-11-17 10:49:00 +08:00 · 2286 次点击
    这是一个创建于 372 天前的主题,其中的信息可能已经有所发展或是发生改变。

    一个控制系统,发送端发送指令,接收端(不是自研,可能是 x86 ,可能是 plc ,pxi 设备等)接收指令。想问一下,在接收端做不到有能力处理重复消息或保证消息幂等的情况下,是不是无法同时保证这个消息的:

    1. 可靠性,消息不丢
    2. 及时送达, 消息第一时间被送达响应。
    23 条回复    2023-11-30 17:51:31 +08:00
    affmans
        1
    affmans  
       2023-11-17 10:53:05 +08:00
    ack
    cheneydog
        2
    cheneydog  
       2023-11-17 10:59:38 +08:00
    参考 mqtt
    laminux29
        3
    laminux29  
       2023-11-17 11:01:10 +08:00
    消息的可靠性就是靠重复率来保证的。

    如果客户端做不到处理重复消息,就没办法保证消息的可靠性。

    换个方案,要不提高客户端的配置,要不就放弃消息的可靠性。
    xxxyangyu
        4
    xxxyangyu  
    OP
       2023-11-17 11:13:29 +08:00
    @affmans ack 没收到,不代表接收端没收到,然后不能处理重复消息。。
    xxxyangyu
        5
    xxxyangyu  
    OP
       2023-11-17 11:14:15 +08:00
    @laminux29 同意你的看法。
    Chinsung
        6
    Chinsung  
       2023-11-17 12:32:20 +08:00
    参考下 TCP ,可以解决重发的问题,只能类似于建立连接的方式,然后确保 syn
    julyclyde
        7
    julyclyde  
       2023-11-17 12:57:53 +08:00
    你要说把“啥都做不到”作为前提,那就别指望解决问题了
    tool2d
        8
    tool2d  
       2023-11-17 13:32:00 +08:00
    TCP 协议本身就是可靠的。

    UDP 你要本地测一下丢包率,如果局域网网线对接,丢包率小于 0.0000001%,那也可以近似看成是可靠的。
    xxxyangyu
        9
    xxxyangyu  
    OP
       2023-11-17 13:33:49 +08:00
    @julyclyde 被控端类型太多,而且由不同供应商组成。没办法做统一约束
    xxxyangyu
        10
    xxxyangyu  
    OP
       2023-11-17 13:43:42 +08:00
    @Chinsung 意思是重复问题交给协议栈解决,业务只要发一次就可以了么
    sujin190
        11
    sujin190  
       2023-11-17 13:45:52 +08:00
    @xxxyangyu #9 你这个是使用场景不匹配的问题吧,plc ,pxi 设备之所以这么设计协议估计就首先约定控制端在同一物理位置且通过可靠忘了连接,你非要弄到公网或者弱网下用,不单独添加设备侧得本地网关保证可靠性,显然是不能的吧
    kuanat
        12
    kuanat  
       2023-11-17 14:01:01 +08:00
    “接收端做不到有能力处理重复消息或保证消息幂等”

    换个表述方式,意思是不是

    "接收端只接收,不响应"?

    很多工控系统是这样设计的,设计的时候就没有“协议”这个概念,接收端“无脑”执行所有指令,默认输入信令永远正确且实时。(因为它可能就是一台单独的设备,从来没考虑过远程控制)

    即使有响应,也不代表能正确处理“重复”指令。很多“响应”的意思是收到指令而已,并不代表指令的执行结果。(因为这类工控系统的指令执行结果是肉眼可见的)
    koloonps
        13
    koloonps  
       2023-11-17 14:03:53 +08:00
    @tool2d "TCP 协议本身就是可靠的",不代表指令是可靠的.存在接收到消息但是没有执行的情况.
    ZZ74
        14
    ZZ74  
       2023-11-17 14:20:36 +08:00
    @koloonps 那和发送端无关,发送端能保证的就是在协议允许的情况下保证对方收到了。收到和执行是两个事情。
    xxxyangyu
        15
    xxxyangyu  
    OP
       2023-11-17 14:23:07 +08:00
    @kuanat "接收端只接收,不响应"? 是有回令的。但是回令其实是个单独的信号,还有可能是总线的。指令执行的结果到是不用太管,正确错误都无所谓。
    所以我要保证的是,这条指令发了,然后收到了。
    xxxyangyu
        16
    xxxyangyu  
    OP
       2023-11-17 14:24:35 +08:00
    @sujin190 不是在公网或弱网下啊。就是本地内网,但是可靠性要求实在是太高了。
    xxxyangyu
        17
    xxxyangyu  
    OP
       2023-11-17 14:28:44 +08:00
    GPT4 的回答:
    在您描述的场景中,如果接收端不能处理重复的消息或保证消息的幂等性,同时保证消息的可靠性(不丢失消息)和及时性(快速送达)确实是一个挑战。这主要是因为在大多数消息队列系统中,为了保证消息的可靠性,通常会采用至少一次( at-least-once )或者精确一次( exactly-once )的消息传递语义:

    1. **至少一次( At-least-once )**:保证消息至少被传递一次,但可能会导致消息重复。在这种情况下,接收端需要能够处理重复消息或实现消息的幂等性。

    2. **精确一次( Exactly-once )**:保证每个消息只被传递一次。这是最理想的,但也是最难实现的,因为它需要在发送端、消息队列系统和接收端之间进行复杂的协调。

    3. **最多一次( At-most-once )**:消息可能会丢失,但不会重复传递。

    在您的情况下,由于接收端不能处理重复的消息或实现幂等性,您可能需要采用以下策略:

    - **使用可靠的消息传递机制**:选择一个支持至少一次或精确一次传递语义的消息队列系统,如 Kafka 的精确一次语义或 RabbitMQ 的消息确认机制。

    - **减少消息重复的可能性**:虽然接收端不能处理重复消息,但可以通过减少网络问题、提高发送端和消息队列系统的可靠性来降低消息重复的风险。

    - **使用超时和重试机制**:在发送端实现超时和重试逻辑,如果在预定时间内未收到确认,可以重发消息。这提高了消息送达的可靠性,但可能增加重复消息的风险。

    - **外部协调**:如果可能,可以在系统外部实现一种机制来跟踪消息的状态,并在消息重复时协助接收端处理。

    - **消息唯一标识**:在消息中包含唯一标识符,并在接收端实现一定程度的逻辑来检测重复的消息,即使不能完全处理它们,也能至少识别出它们。

    需要注意的是,即便采用了上述策略,如果接收端完全无法处理重复消息,那么在网络不稳定或系统出现故障时,仍然可能面临挑战。在这种情况下,可能需要重新考虑系统的设计,或者在接收端实现一些基本的幂等性处理逻辑。
    leonshaw
        18
    leonshaw  
       2023-11-17 14:29:46 +08:00
    两军问题
    koloonps
        19
    koloonps  
       2023-11-17 15:17:49 +08:00
    @ZZ74 人家要求的是控制消息可靠啊,tcp 可靠有什么用.
    zealotxxxx
        20
    zealotxxxx  
       2023-11-17 16:08:27 +08:00
    假设不可靠,然后根据不可靠来考虑怎么确保能执行。
    物联网这块不是很多的么?
    fz420
        21
    fz420  
       2023-11-17 20:47:31 +08:00
    future0906
        22
    future0906  
       2023-11-17 23:37:37 +08:00
    也不一定无办法解决,主要是看发送端和接收端是用什么协议栈。如果是标准 TCP 的话还有点戏
    Chinsung
        23
    Chinsung  
       359 天前
    @xxxyangyu 是在业务层再做一层 TCP 这种 SYN 和 ACK 维护通信序列号的模式,以此来支持重发,简单点就下游做个通信流水记录,以此来丢弃重发的消息
    如果接收端完全不可编程实现功能,那无解,只能依赖 TCP
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2970 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 00:14 · PVG 08:14 · LAX 16:14 · JFK 19:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.