broadcast 广播
介绍
广播是通讯方式之一,广播也称推送。常用于主动给一个、多个或全服的用户发送一些数据。比如:
- 一个 : 给指定的在线玩家发送一些奖励。
- 多个 : 给在同一个房间内的玩家广播一些数据,如某一个玩家射击子弹,把这子弹的数据广播给房间内的其他玩家。
- 全服 : 给全服的所有在线玩家广播消息,如广播公告、即将停服维护等。
广播上下文提供了两种类型
- BroadcastOrderContext 严格顺序的 广播上下文(单线程的)
- BroadcastContext 默认的广播上下文 (多线程的)
使用广播需要的两个参数,分别是:1. 路由地址、2.需要广播的业务数据。
public void testBroadcastOrderContext() {
var broadcastOrderContext = BrokerClientHelper.getBroadcastOrderContext();
for (int i = 0; i < 10; i++) {
var data = IntValue.of(i);
broadcastOrderContext.broadcastOrder(cmdInfo, data);
}
}
public void testBroadcastContext() {
var broadcastContext = BrokerClientHelper.getBroadcastContext();
broadcastContext.broadcast(cmdInfo, data);
}
如果没有特殊业务需求,建议使用性能更好的 BroadcastContext。 因为实际的业务中,关于战斗中的广播都是会设置一个类似帧率的参数,只要不是太密集基本都没问题。 可以巧妙的利用帧率间隔来达到顺序广播。
BroadcastContext 与 BroadcastOrderContext 的使用方式上基本是一致的。
通过 FlowContext 广播
FlowContext 内置了一些广播的便捷方法。
@ActionController(1)
public class MyBroadcastAction {
...
@ActionMethod(1)
public void hello(FlowContext flowContext) {
flowContext.broadcast(cmdInfo1, StringValue.of("hello"));
flowContext.broadcast(cmdInfo2, StringValue.of("hello userId"), userId);
flowContext.broadcast(cmdInfo3, StringValue.of("hello userIdList"), userIdList);
flowContext.broadcastMe(cmdInfo4, StringValue.of("hello broadcastMe"));
}
}
BroadcastContext 与 FlowContext 的区别
默认情况下,广播会给所有的游戏对外服发送消息,因为我们的架构是支持启动多个游戏对外服的。
FlowContext 记录了玩家的信息,能知道玩家所属的游戏对外服,这在广播时可以节约一些机器资源的占用。
使用 FlowContext.broadcastMe
进行广播时,内部会设置好这些信息。
在使用 BroadcastContext 时,你也可以手动设置游戏对外服信息。
...
private static void extracted(String externalId) {
var bizData = new DemoBroadcastMessage();
broadcastMessage.msg = "broadcast hello!";
CmdInfo cmdInfo = ...;
ResponseMessage responseMessage = BarMessageKit.createResponseMessage(cmdInfo, bizData);
HeadMetadata headMetadata = responseMessage.getHeadMetadata();
int sourceClientId = HashKit.hash32(externalId);
headMetadata.setSourceClientId(sourceClientId);
BroadcastContext broadcastContext = BrokerClientHelper.getBroadcastContext();
broadcastContext.broadcast(responseMessage);
}
@ToString
@ProtobufClass
public class DemoBroadcastMessage {
public String msg;
}
RangeBroadcast 范围广播便捷工具
RangeBroadcast 范围内的广播功能,这个范围指的是,可指定某些用户进行广播。
RangeBroadcast 提供了一些便捷的方法
- 添加一些需要广播的用户
- 删除一些不需要接收广播的用户
- 可通过重写 logic、trick 方法来做一些额外扩展
- 提供了便捷的装箱、拆箱方法
创建
var rangeBroadcaster = RangeBroadcaster.of(flowContext);
// or
var brokerClient = BrokerClientHelper.getBrokerClient();
var aggregationContext = brokerClient.getCommunicationAggregationContext();
var rangeBroadcaster = RangeBroadcaster.of(aggregationContext);
下面两个方法是等价的
void test1() {
RangeBroadcaster.of(flowContext)
.setResponseMessage(cmdInfo, StringValue.of("hello"))
.addUserId(1)
.execute();
}
void test1() {
RangeBroadcaster.of(flowContext)
.setResponseMessage(cmdInfo, "hello")
.addUserId(1)
.execute();
}
关于 RangeBroadcaster 更详细的介绍请阅读 javadoc。
开启广播日志
在构建业务框架时,可以通过配置来开启广播的日志。
public class DemoBroadcastServer extends AbstractBrokerClientStartup {
@Override
public BarSkeleton createBarSkeleton() {
var config = new BarSkeletonBuilderParamConfig()
.scanActionPackage(BroadcastMessageAction.class)
.setBroadcastLog(true);
...
}
}
console
┏━━━━━ 广播. [(DemoBroadcastApplication.java:40)] ━━━ [cmd:7 - subCmd:0 - cmdMerge:458752]
┣ userId: 全服广播
┣ 广播数据: DemoBroadcastMessage(msg=broadcast hello ,253)
┣ 广播时间: 2022-05-19 21:31:47.728
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┏━━━━━ 广播. [(DemoBroadcastApplication.java:40)] ━━━ [cmd:7 - subCmd:0 - cmdMerge:458752]
┣ userId: 1
┣ 广播数据: DemoBroadcastMessage(msg=broadcast hello ,1)
┣ 广播时间: 2022-05-19 21:32:42.732
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┏━━━━━ 广播. [(TankAction.java:116)] ━━━ [cmd:2 - subCmd:7 - cmdMerge:131079]
┣ userId: [1,5,7]
┣ 广播数据: BarHelloPb(amount=7)
┣ 广播时间: 2022-07-14 18:31:02.253
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
注意事项
指定玩家列表广播时,玩家列表不能使用 List.of()
,而需要使用 ArrayList
,否则会导致 bolt RpcClient 序列化报错无法广播。
引发异常的示例
var data = StringValue.of("biz data");
// error
List<Long> userIdList = List.of(1L, 2L, 3L);
broadcastContext.broadcast(cmdInfo, data, userIdList);
Example Source Code
see https://github.com/iohao/ioGameExamples
path : SimpleExample/example/example-broadcast
- DemoBroadcastApplication