Skip to content
crazyjohn edited this page Jan 14, 2016 · 6 revisions

stupidbird

stupid是一个基于java语言的框架,设计用来开发高性能的游戏服务器但是不限于游戏服务器。

  1. 架构简述

设计初衷出发于游戏服务器引擎,所以我从游戏服务器的角度来描述。游戏服务器的承载最后都会摊派到服务器的几个资源:CPU,内存,硬盘等。这其中CPU负责运算,内存用来存储游戏热数据,经常会用到一些时空权衡的思想,硬盘用来最终落地数据,或者叫做数据固化,考量的主要是容量和iops以及带宽。

那么设计良好的引擎模型一定是有以下特点:

  1. 可以最大限度(或者最优或者最合适)的利用其这些资源,也就是首先要做到可以合理的scale up纵向扩展。
  2. 接口足够少,设计足够简单。方便程序员学习和快速上手。
  3. 设计足够灵活。方便功能切入和扩展。
  4. 代码如湿。

下面来个stupidbird的内部组件鸟瞰:

这基本是所有的切入组件,了解这些你就已经get到了引擎的一切:

  1. Node。代表一个服务节点,目前有两个实现:ServerNode和Commander。接口也足够简单和少。

    1. config。来为节点加载配置。当然不调用的话节点会使用默认的配置。
    2. setDispatcher。用来设置节点的分发器,用来分发节点收到的消息。
    3. executor。用来获取节点的执行器。
    4. registerShutdownHook。用来注册停机钩子。
    5. setIoHandler。用来设置io处理器,也是业务的切入入口。
  2. NodeDispatcher。是分发器,设计用来分发消息。

  3. NodeExecutor。是执行器,用来处理网络消息或者系统内部事件。

  4. ObjectKeyGenerator。是key生成器,执行器用此来生成绑定对象的key。

  5. NodeIoHandler。是io处理器,也是业务的入口,这里用来创建和业务对象绑定的网络会话。

  6. NodeBindableSession。这就是绑定业务对象的网络会话。

然而在其中,你只需要切入实现两个部分:NodeIoHandlerNodeBindableSession

public class CommanderServerApp {

	public static void main(String[] args) throws Exception {
		Commander commander = new Commander();
		commander.setIoHandler(new ServerExampleIoHandler(commander));
		commander.startup();
	}

}

上面这几行码你就可以启动一个Commander服务器,并且使用telnet与之交互。然后再在上头说到的两个部分注入你的业务。

  1. 整体层次

  1. 消息层 : protobuf packet

  2. 网络层 : mina

  3. 序列化层 : protobuf

  4. 执行层 : actor

  5. 缓存层 : local + redis strategy

  6. 数据层 : strategy - mongo + morphia

  7. 执行层


  1. 执行层使用多线程驱动,线程数量可配置,完全解开线程结构和业务结构之前的耦合。

  2. Poision模式进行执行器的graceful stop。

  3. 线程安全使用acotr模式。actor之间通信使用tell and forget。

  4. 使用对象绑定线程的方式执行,抽象出keyGenerator供使用者切入。

  5. 缓存层


整体抽象抽了DBAgent这层中间层。实现EntityDBService接口并且聚合了缓存接口KVClient,缓存这里可以实现多个策略,目前有redis和本地缓存。不过目前代理这里设计的不够完善,下个版本去搞。

  1. LocalCache

  2. Redis

  3. 数据层


数据层使用异步更新的方式,解耦数据生产者和消费者。

  1. 抽象出EntityDBService策略。目前有mongodb实现和cassandra实现。Entity代表会引入ORM的概念,关于用不用ORM取决于它能让我有多方便和它有多降低效率。

  2. 提倡使用mongodb3.2+。原因是3.2+以后引擎由原来的mmapv1换成了wiredtigger。wiredtigger整体表现比较稳定,而且很多特性跟innodb很像。

  3. cluster集群的方案后续添加。

  4. 模板层


目前使用基于@hawk的orm方案。但是后期会重构这里,使用DSL的模式,让这一切都自动化。

  1. 脚本支持

引擎内置js脚本引擎支持,可以支持把js脚本映射成java类,其中Node的启动配置就是通过这种方式加载的。

js脚本:

// ===== import begin =====//

//=====  import end   =====//


config.name = "game";
// bind ip
config.bindIp = "0.0.0.0";
// bind port 
config.port = 8001;
// telnet ip
config.telnetIp = "0.0.0.0";
// telnet port
config.telnetPort = 7001;
// 消息处理线程个数
config.msgThreadCount = 4;
// 数据处理线程个数
config.dbThreadCount = 4;
// 数据库连接
config.dbHost = "127.0.0.1";
// mongo:27017
// cassandra:9042
config.dbPort = 27017;
config.dbName = "stupidbird";

对应的映射java文件:

/**
 * 游戏服务器配置;
 * 
 * @author crazyjohn
 *
 */
public class GameServerConfig extends ServerConfig {
	private String dbHost;
	private int dbPort;
	private String dbName;
	private int dbThreadCount;

	public String getDbHost() {
		return dbHost;
	}

	public void setDbHost(String dbHost) {
		this.dbHost = dbHost;
	}

	public int getDbPort() {
		return dbPort;
	}

	public void setDbPort(int dbPort) {
		this.dbPort = dbPort;
	}

	public String getDbName() {
		return dbName;
	}

	public void setDbName(String dbName) {
		this.dbName = dbName;
	}

	public int getDbThreadCount() {
		return dbThreadCount;
	}

	public void setDbThreadCount(int dbThreadCount) {
		this.dbThreadCount = dbThreadCount;
	}

}
Clone this wiki locally