远程通讯
Remoting 启用、Codec、RegisterCustomMessage 与位置透明
跨节点 Actor 通信需在创建 ActorSystem 时启用 Remoting 并配置消息编解码(Codec 或 RegisterCustomMessage)。配置完成后,本地与远程的消息投递对业务透明:同一套 API(Tell、Ask、Reply、PipeTo 等)不因目标在本机或远程而改变,无需改写调用方式或增加分支;框架根据 ActorRef 的地址自动选择本地投递或跨网络发送,并完成序列化与反序列化。本文说明如何启用 Remoting、配置 Codec 或 RegisterCustomMessage,以及远程连接读失败时的处理。入口配置见 Actor System 配置。
位置透明
配置好 Remoting 与 Codec 后,业务侧无需区分目标 Actor 在本机还是远程:ctx.Tell(ref, msg)、ctx.Ask(ref, msg) 等调用方式完全一致,框架根据 ref 的地址自动完成本地投递或跨网络序列化与发送。这就是 location transparency(位置透明)。
启用 Remoting
通过 WithActorSystemRemoting(bindAddr, advertiseAddr?) 启用:
- bindAddr(必填):本机监听地址,如
"0.0.0.0:8080"。框架在此地址上启动 Listener 接受连接。 - advertiseAddr(可选):对外暴露地址,如公网 IP 或集群内域名+端口,供其它节点连接。不传则使用 bindAddr。若 advertiseAddr 缺端口且非域名,会 panic;缺端口的域名会由框架或上层补充处理。
TCP 与 UDP 是否复用同一端口以当前版本实现与发布说明为准。
编解码(二选一)
跨网络传递的消息必须可序列化。两种方式任选其一:
统一 Codec
WithActorSystemCodec(codec):所有消息的序列化/反序列化均通过该 Codec 完成。Codec 接口为:
type Codec interface {
Encode(message Message) ([]byte, error)
Decode(data []byte) (Message, error)
}可由业务实现 JSON、MessagePack、Proto 等格式。codec 不能为 nil。适用于消息种类多、希望统一格式或已有现成编解码库的场景。
若希望直接使用 Protocol Buffers 作为 Remoting 消息格式,可使用官方维护的 vivid-proto,接入方式为 vivid.WithActorSystemCodec(codec.New())。完整说明见 集成:vivid-proto。
按类型注册(RegisterCustomMessage)
未使用统一 Codec 时,需为每一种需要跨节点传输的自定义消息类型调用 RegisterCustomMessage 注册 reader/writer:
- messageName:消息在系统中的唯一名称,建议与类型名一致,用于网络协议中区分类型。
- reader(CustomMessageReader):反序列化时被调用,将字节流按序填入 message。
- writer(CustomMessageWriter):序列化时被调用,将 message 的字段按序写出。
读写顺序必须一致。函数签名与 reader/writer 参数类型见 pkg.go.dev - RegisterCustomMessage。注册应在 init 或应用启动时完成,仅需一次。适用于希望按类型精细控制二进制格式、或与现有协议兼容的场景。
必选其一
跨网络传递消息必须:要么设置 WithActorSystemCodec,要么为所有需要远程传输的自定义消息类型 RegisterCustomMessage,否则远程通信会失败。
远程连接读失败处理
通过 WithActorSystemRemotingOptions 传入 ActorSystemRemotingOptions,可设置 ConnectionReadFailedHandler,在远程连接读取失败时被调用(如对端断开、网络异常、超时):
- HandleRemotingConnectionReadFailed(fatal bool, err error) error
- fatal:是否为致命错误(如 true 可能触发连接关闭或更高级别处理)。
- err:具体错误。
- 返回 非 nil 时,该连接会被关闭并将该 error 作为停止原因;返回 nil 表示忽略或已自行处理。
可使用 ActorSystemRemotingConnectionReadFailedHandlerFN 以函数形式实现,便于在连接失败时打日志、告警或做重试策略。
远程连接重试与死信
向远程节点发送消息时,若连接不可用,框架会按 ActorSystemRemotingOptions 中的重试策略进行有限次重试(指数退避)。默认通过 NewActorSystemRemotingOptions() 提供:重试次数 10、初始延迟 500ms、最大延迟 10s、退避因子 2.5、启用抖动。可通过 WithActorSystemRemotingOption 链式配置单项或使用 WithActorSystemRemotingReconnect 批量配置:
- ReconnectLimit:重试次数,<1 则不重试(0 表示不重试)。对应 WithActorSystemRemotingReconnectLimit。
- ReconnectInitialDelay / ReconnectMaxDelay:初始与最大延迟。WithActorSystemRemotingReconnectInitialDelay、WithActorSystemRemotingReconnectMaxDelay。
- ReconnectFactor:退避因子(如 2.0 表示指数退避)。WithActorSystemRemotingReconnectFactor。
- ReconnectJitter:是否启用抖动,缓解重连雷群。WithActorSystemRemotingReconnectJitter。
重试期间会向事件流发布 ves.RemotingConnectionFailedEvent(含 RemoteAddr、Error、RetryCount 等),可订阅该事件做监控。若在重试次数用尽后仍无法投递,该消息会作为死信投递(即 HandleFailedRemotingEnvelop 将 Envelope 投递到死信队列),可通过订阅 ves.DeathLetterEvent 进行监控与审计,参见 死信。
未启用 Remoting 时,向远程 ActorRef 发送消息会得到“远程未启用”的告警,且该消息不会跨节点发送(由框架按当前实现处理,例如落入系统邮箱),业务侧应避免在未启用 Remoting 的节点上向远程 ref 发信。
远程消息发送、编解码、握手或处理失败时会返回 ErrorRemotingMessageSendFailed、ErrorRemotingMessageEncodeFailed、ErrorRemotingMessageDecodeFailed、ErrorRemotingMessageHandleFailed、ErrorRemotingHandshakeFailed 等,详见 错误。
与集群配合
在启用 Remoting 的前提下,可通过 WithActorSystemRemotingOptions 传入 WithActorSystemRemotingClusterOption 或 WithActorSystemRemotingClusterOptions 启用集群。集群使用 Remoting 的地址与编解码进行节点间成员发现与通信。详见 集群。
与引用解析配合
远程节点的引用常以字符串形式存储或从配置/服务发现获取。使用 system.ParseRef(actorRef string) 可将字符串解析为引用(不要求目标存在),再用于发消息。详见 Actor 引用。