不止 request/response —— ionet 的 4 种通信模型选型指南

为什么通信模型如此重要?

很多项目把所有的网络交互都做成一种模式:客户端发请求、服务器回响应。这在简单场景下没有问题,但随着业务复杂度的增加,你会遇到这些困境:

  • 进入房间后,如何给所有人推送状态变化? 用 request/response 需要客户端主动轮询,既浪费带宽又有延迟。
  • 匹配系统需要查询多个逻辑服的负载情况,如何一次请求获取多个响应? 用 request/response 需要串行调用,效率低下。
  • 玩家登录后需要通知多个系统(邮件、任务、活动),如何解耦? 都塞在登录方法里,代码臃肿到无法维护。

选对通信模型,业务代码会更清晰,性能和可维护性也更稳。

ionet 提供了 4 种通信模型,覆盖几乎所有场景。本文将逐一解析,并给出选型建议。


模型一:request/response ------ 最经典的交互

这是最常见的通信方式:客户端发送请求,服务器返回一个响应。

java 复制代码
@ActionController(1)
public class HallAction {
    @ActionMethod(0)
    private UserMessage loginVerify(LoginVerifyMessage message) {
        var userMessage = new UserMessage();
        userMessage.name = "Hello, " + message.jwt;
        return userMessage;
    }
}

适用场景:登录验证、数据查询、表单提交------所有"问一句答一句"的业务。

特点

  • 一次请求,一次响应
  • 最简单、最直观
  • 支持跨进程跨机器调用

模型二:request/multiple_response ------ 分段返回

当你需要一次请求从多个逻辑服收集数据时,这个模型就派上用场了。

典型场景:匹配系统需要知道哪个房间逻辑服最空闲。你启动了 3 个房间逻辑服,需要一次请求拿到每个逻辑服的房间数量。

java 复制代码
// 匹配逻辑服中发起请求
var communication = CommunicationKit.getCommunication();

// 向所有同类型逻辑服广播请求,收集多个响应
var responseItems = communication.requestMultipleResponse(cmdInfo, requestData);

// 找到房间数最少的那个
var bestServer = responseItems.stream()
    .min(Comparator.comparingInt(item -> item.roomCount))
    .orElseThrow();

适用场景

  • 查询多个逻辑服的状态(负载均衡)
  • 收集分布式系统中的聚合数据
  • 类似 LOL/王者荣耀的匹配后资源分配

特点

  • 一次请求,多个响应(每个逻辑服实例返回一个)
  • 支持流式感知
  • 适合分布式数据收集

模型三:broadcast ------ 广播推送

当服务器需要主动向多个客户端推送消息时使用广播。游戏中最常见:房间内玩家的每次操作,都需要同步给其他所有玩家。

java 复制代码
@ActionMethod(3)
private void triggerBroadcast() {
    var communication = CommunicationKit.getCommunication();

    // 广播一个对象给所有在线玩家
    var message = new HelloMessage();
    message.name = "有新活动开启了!";
    communication.broadcastMulticast(cmdInfo, message);
}

适用场景

  • 房间内状态同步(棋牌游戏、对战游戏)
  • 全服公告
  • 实时排行榜更新
  • 聊天消息分发

特点

  • 服务器主动推送,客户端被动接收
  • 支持全体广播和定向广播
  • 即使启动了多个对外服,框架也会确保所有在线用户都能收到消息

关于最后一点:当你有多个对外服时,用户分布在不同的对外服上。框架会自动处理跨对外服的消息分发------在开发者眼中,只有"一个"对外服。


模型四:EventBus ------ 分布式事件总线

这是 ionet 最强大、最独特的通信方式。它类似于 Redis pub/sub 和 MQ,但完全不需要安装任何中间件

为什么需要事件总线?

回到之前的例子:玩家登录后,需要做这些事------

  1. 记录登录时间
  2. 计算离线奖励
  3. 发送欢迎邮件
  4. 检查任务完成状态

如果把这些逻辑都塞在登录 Action 里,代码会变得臃肿、耦合严重。

用事件总线的做法:

1. 定义事件源

java 复制代码
@ProtobufClass
public class UserLoginEventMessage {
    public long userId;

    public static UserLoginEventMessage of(long userId) {
        var message = new UserLoginEventMessage();
        message.userId = userId;
        return message;
    }
}

2. 编写订阅者

java 复制代码
@EventBusSubscriber
public class EmailEventBusSubscriber {
    @EventSubscribe
    public void mail(UserLoginEventMessage message) {
        log.info("发送欢迎邮件给用户 {}", message.userId);
    }
}

@EventBusSubscriber
public class RewardEventBusSubscriber {
    @EventSubscribe
    public void calcReward(UserLoginEventMessage message) {
        log.info("计算离线奖励给用户 {}", message.userId);
    }
}

3. 发布事件

java 复制代码
@ActionMethod(0)
private UserMessage login(FlowContext flowContext, LoginMessage message) {
    // 发布登录事件 ------ 所有订阅者都会收到
    flowContext.fire(UserLoginEventMessage.of(flowContext.getUserId()));

    // 返回登录结果
    return new UserMessage("登录成功");
}

登录方法干干净净,只做登录的事。邮件、奖励、任务等逻辑分散在各自的订阅者中------它们可以在不同的逻辑服中,甚至在不同的机器上。

EventBus 的独特优势

ionet 的分布式事件总线与 Redis pub/sub 和 MQ 相比,有几个独特的优势:

特性 ionet EventBus Redis pub/sub / MQ
安装依赖 需要安装中间件
全链路追踪 ✅ 支持 ❌ 不支持
跨进程跨机器 ✅ 支持 ✅ 支持
无订阅者时的行为 不触发网络请求 仍然发送消息到中间件
费用 免费 Redis/MQ 需要服务器费用

其中**"无订阅者时不触发网络请求"**是一个非常精妙的设计。这意味着你可以放心地在业务中埋点(发布事件),不用担心性能开销------只有当有订阅者在线时,才会触发实际通信。

EventBus 的发布方式

框架提供了多种发布粒度:

方法 范围
fireMe 仅当前逻辑服的订阅者
fireLocal 当前进程内所有逻辑服的订阅者
fire 所有订阅者(含远程)
fireAny 同类型逻辑服中只发给其中一个

每种方法都有同步和异步版本。


选型指南

场景 推荐通信模型 理由
登录、查询、更新 request/response 一问一答,最简单
匹配后选最空闲节点 request/multiple_response 需要多个逻辑服同时返回
房间内操作同步 broadcast 服务器主动推送给多人
全服公告 broadcast 面向所有在线用户
登录后触发多系统 EventBus (fire) 解耦,支持跨进程
统计数据收集 EventBus (fireAny) 只需一个实例处理
热更配置 EventBus (fire) 所有实例批量更新
临时活动上下线 EventBus 逻辑服下线 = 订阅者消失 = 零开销

所有通信方式的共同特性

无论你使用哪种通信模型,ionet 都保证:

  1. 支持跨进程、跨机器通信
  2. 具备全链路调用日志跟踪(每个请求分配唯一 traceId)
  3. 可扩展

这在排查分布式系统问题时非常关键------你可以通过一个 traceId 追踪完整的请求链路,无论请求经过了多少个逻辑服。


小结

通信模型选对了,你的代码就是清晰的;选错了,你就在和框架对抗。

ionet 提供的 4 种通信模型,从最简单的 request/response 到最强大的 EventBus,覆盖了分布式系统中几乎所有的通信场景。更重要的是,它们的使用方式都围绕一个核心设计原则:写起来像调用普通 Java 方法。


更多资源

下一篇预告:[告别 Redis/MQ ------ ionet 分布式事件总线实战]

相关推荐
金蕊泛流霞2 小时前
Spring AI Alibaba笔记
java·笔记·spring
沐伊~2 小时前
LINUX基础篇(Ubuntu):
linux·运维·服务器
艾莉丝努力练剑2 小时前
System V IPC底层原理详解
linux·运维·服务器·网络·c++·人工智能·学习
落羽的落羽2 小时前
【Linux系统】信号机制拆解,透过内核三张表深入本质
android·java·linux·服务器·c++·spring·机器学习
jxkejiiii2 小时前
电脑键盘震动反馈,开启与关闭方法及常见问题解答
java·安全·智能手机
小陳参上2 小时前
持久化数据库实现:确保数据持久性与可靠性
java·jvm·数据库
于慨2 小时前
java Web
java·开发语言·前端
麦麦鸡腿堡2 小时前
JavaWeb_maven
java·开发语言·maven
weixin_457341892 小时前
2026年阿里云ECS服务器全攻略:从基础认知和价格体系到购买以及部署流程
服务器·阿里云·云计算