1: 天龙八部的逻辑处理模块:
逻辑处理模块:
void run
{
for(;;){
select(); //epoll wait();
process_inputs();
process_commands();
process_outputs();
process_execeptions();
}
}
天龙八部的SocketOutputStream 和 SocketInputStream 类设计最大程度的减少了内存拷贝,加上Packet/PacketFactory工厂模式的设计,在很多程度上面提升了单线程处理能力,无论是GameServer BIllingServer LoginServer 都几乎没有加锁的操作,这样也就最大程度上消除了线程调度的性能消耗;如果我们把这个模式引入到页游,那么就可以这样设计:我们将天龙八部的select 模型换成现在流行的epoll模型。
图1: 服务器的分布
无论验证服,聊天服,还是场景服都做类似的处理模式。场景内还需要添加日志线程、流水线程,专门用于处理日志的打印和流水的迁移。
这个模式的优点:
1: 每个角色对应一个连接,能够方便的处理消息,减少附加数据结构的设计
2: 内存拷贝少
3: 单个进程内所有的玩家都在同一个进程,玩家之前的交互逻辑很容易处理
这个模式的缺点:
1:不能充分利用现在多核的设计
2: 另一种处理模式:
图 2 另一种设计
通信线程:
void run()
{
for(;;){
select(); //select epoll wait();
process_input();
process_output();
process_disconnect();
}
}
逻辑处理逻辑:
void run()
{
while(TRUE)
{
Packet* packet = NULL;
PacketList.pop(packet);
if(packet != NULL)
{
process_packet(packet);
}
}
}
这里的通信模块更像是一个网关,通信模块和逻辑处理模块之间是经典的生产者和消费者模式,无论是采用巧夺天工的Kfifo设计还是使用自旋锁设计都可以,只是要尽量解除线程切换和等待。
这个模式的优点
1: 能配置成多线程处理,比如 n:m
缺点:
1: 内存拷贝多
2: 数据迁移之后,需要map去映射玩家和连接
感想:
页游服务器相对来说是端游服务器的弱化版,当然我们也可以设计一个网关服去加大服务器承载的玩家数量,但是这样经过不同进程之间转发的消息又必然会带来很多同步问题,比如帮派和组队逻辑要坐在世界服,而走动打斗逻辑要做在场景服,在玩家在场景之间切换的时候或者一些帮派、好友数据需频繁同步。上面的两种模式不过是工作之余的思考,和参考其他的网友的分享想到的,还有很多的数据没有经过测试,比如在内存拷贝、线程同步与多线程之间如何取舍。还是很想听听其他网友的意见。