在计算机科学中,消息传递()是一种在计算机上调用行为(即运行程序)的技术。调用程序向一个进程(可能是参与者或对象)发送消息,依赖该进程及其基础设施来选择和运行相应的代码。消息传递不同于传统的直接通过名称调用进程、子程序或函数的编程方式。它是并发计算、并行计算、面向对象程序设计和进程间通信中的关键技术。消息传递在当今计算机软件中无处不在,既用于同一程序中对象之间的协作,也用于运行在不同计算机上的系统和对象之间的交互(例如互联网)。
概述
消息传递是一种通信范式,由发送者将消息传递给一个或多个接收者。消息的形式因操作系统和编程语言的支持而异,常见的有方法调用、信号和数据包。与直接调用不同,消息传递使用对象模型将通用功能与具体实现区分开来:调用程序发送消息,由对象自行选择和执行适当的代码。使用这一中间层的理由主要分为两类:封装和分布。
封装意味着软件对象可以在不了解或关心其他对象如何实现服务的情况下调用其服务,这减少了编码中的判断逻辑,使系统更易于维护。例如,在计算机图形学中,计算不同形状(三角形、矩形、椭圆、圆形)的面积需要不同的公式。传统编程需要使用大量IF-THEN语句判断形状类型;而在面向对象方式中,只需定义一个Shape基类及其子类,向任何形状对象发送“计算面积”的消息,对象便会自动调用适合其类型的方法。
分布式消息传递为构建运行在不同计算机上的子系统提供了基础设施层。该层负责处理以下问题:定位目标进程(可能在不同操作系统和编程语言中)、将消息存入队列以便在目标对象可用时处理,以及控制分布式事务所需的ACID特性。
同步与异步
消息传递系统可根据发送和接收操作与执行进程的交互方式分为同步和异步两大类。
同步消息传递
在同步消息传递中,发送进程在接收进程接受消息之前会阻塞等待。这类似于同步函数调用:调用者等待被调函数完成后才继续执行。同步通信在面向对象语言(如Java和Smalltalk)中广泛使用,但对于大型分布式系统可能不适用——如果某个子系统的计算机宕机,整个系统的其他部分可能被阻塞。
异步消息传递
在异步消息传递中,发送者在发送消息后继续执行,消息通常存储在队列或缓冲区中,直到接收进程检索处理。异步通信需要额外的软件层(通常称为消息中间件,MOM)来存储和转发数据。其潜在问题是缓冲区满时的处理策略:要么阻塞发送者(可能导致死锁),要么丢弃后续消息(导致通信不可靠)。
混合方式
同步通信可以在异步通信之上构建,例如使用α-同步器(α-Synchronizer):发送者必须等待接收方的确认消息才能发送下一条。同样,异步通信也可以在同步通信之上构建,例如现代微内核通常只提供同步消息传递原语,通过辅助线程实现异步通信。
分布式对象
在分布式对象消息传递中,发送者和接收者可能位于不同计算机上,运行不同操作系统、使用不同编程语言。基础设施层负责数据格式转换、网络传输等细节。远程过程调用(RPC)协议是早期的例子。支持分布式对象的系统包括:ONC RPC、CORBA、Java RMI、DCOM、SOAP、.NET Remoting、QNX Neutrino RTOS、D-Bus等。
分布式消息传递比本地过程调用有额外开销:参数必须被复制到新的消息中,对于包含大量数据的参数,全部复制和传输的成本可观。传统过程调用通过寄存器或地址列表传递参数,不需要额外存储或传输时间,但地址传递在分布式系统中不可行,因为系统使用独立的地址空间。
数学模型
消息传递的主要数学模型是演员模型和π演算。在数学意义上,消息是将控制权传递给对象的唯一手段;如果对象响应某条消息,则说明它具有处理该消息的方法。
艾伦·凯曾指出,在面向对象编程中消息传递比对象本身更为重要,对象本身常常被过度强调。活跃分布式对象编程模型建立在这一观察之上,通过消息模式来描述复杂分布式系统的行为。
使用消息传递的编程语言
下列编程语言以消息传递为核心特性:Erlang、Elixir、Go、Objective-C、Rust、Scala、Smalltalk、Self、Concurrent ML、AppleScript、HyperCard和LiveCode。
参考文献
参见
- 分布式计算
- 消息传递接口
- 通信顺序进程
- 事件循环
评论 (0)