cocos creator 1.8.2+pomelo+mysql8.0 简单部署测试

目标:我这里要做的目标,就是当一个用户(id为100,name是xiaoming)在房间01(rid=01)买了一个商品(count=1),然后在mysql的商品表格里记录下一条数据,包括用户的id(id=100)和商品的owner(owner=name加上用户的房间号)。

一、安装环境

1、cocos creator 1.8.2 安装

2、pomelo 安装(包括node.js之类)按照官方教程即可,如果不想装vs2010这类占10G硬盘空间的东西,直接npm install --global --production windows-build-tools,需要大约一共2G左右硬盘

3、在官网下载Mysql 8.0.11,安装,这里没什么可说的,至少把server和workbench装一下 。

注意:安装mysql 8.0 的时候碰到一个问题,直接用workbench连接会外部组件报错。细查一下是Authentication plugin 'caching_sha2_password'cannot be loaded。

解决方法:进入mysql 命令行窗口

这里root的密码改为111111,使用老版本的身份验证插件方式: 

ALTER USER root@localhost IDENTIFIED WITH mysql_native_password BY ‘111111’;

4、为了调试方便,建议安装webstorm。

二、安装用到的案例程序和包

1、安装pomelo框架的经典聊天例子chatofpomelo:命令行直接git clone https://github.com/NetEase/chatofpomelo-websocket.git,然后cd chatofpomelo-websocket,执行npm-install.bat(我是win7系统)。

2、命令行进入到game-server目录,安装最新版的generic-pool,npm install generic-pool

3、配置cocos creator客户端的pomelo库可以参照这个贴子:http://forum.cocos.com/t/cocos-creator-pomelo/60036

三、 配置数据库

1、安装好mysql后,用workbench的root进入,创建一个新的schema,起名就叫pomelo吧。然后创建一个新的用户,权限给全,选择users and privileges,在下方有个add account按钮点一下,,用户名叫test,选项卡选administrative roles,都点上,选项卡再选schema privileges,点击add entry,把数据库pomelo的权限都给test。

2、新建个连接,就叫叫testConnection吧,然后edit一下这个连接,用户就用刚刚创建的test。

3、用新连接testConnection进入mysql,在名为pomelo的数据库(就是schema)下创建一个table,叫goods。给这个表建两个column。一个叫id,第二个叫owner

四、配置服务器端

1、配置数据库连接参数

我们这个例子建立在pomelo官方的例子chatofpomelo之上,进入下载的chatofpomelo,由于数据库的连接参数game-server和web-server都需要用到,所以最好放到一个共享目录。在项目根目录建立一个shared目录,再在下面建立个config目录,在config下面新建一个文件mysql.json,配置连接数据库的参数:

{

    "development": {
      "host" : "127.0.0.1",
        "port" : "3306",
        "database" : "pomelo",
        "user" : "test",
        "password" : "1234qwer"
    },
    "production": {
      "host" : "127.0.0.1",
        "port" : "3306",
        "database" : "pomelo",
        "user" : "test",
        "password" : "1234qwer"
    }
}

2、配置数据访问接口(DAO),DAO接在数据库资源和业务逻辑中间,把底层的数据访问逻辑和高层的业务逻辑分开。我们对数据库访问的相关操作就放到这个模块里面。如果后面需要更换数据库什么的,可以直接重写这部分代码即可,而不需要在项目的所有逻辑代码里面到处去改sql语句。

在game-server/app下新建文件夹dao,dao下面再新建mysql文件夹。进入mysql文件夹,新建dao-pool.js和mysql.js。
var _poolModule = require('generic-pool');

//导入mysql模块,创建数据库连接需要
var mysql = require('mysql');

/*
 * Create mysql connection pool.
 */
var createMysqlPool = function(app){
	var mysqlConfig = app.get('mysql');
	const factory = {
		create: function(){
			return new Promise(function(resolve, reject){
				var client = mysql.createConnection({
					host: mysqlConfig.host,
					user: mysqlConfig.user,
					password: mysqlConfig.password,
					database: mysqlConfig.database
				});
				resolve(client);
			});
		},
		destroy: function(client){
			return new Promise(function(resolve){
				client.on('end', function(){
					resolve()
				});
				client.disconnect()
			});
		}
	}
  	return _poolModule.createPool(factory, {max:10, min:2});
};

exports.createMysqlPool = createMysqlPool;
// mysql CRUD
var sqlclient = module.exports;

var _pool;

var NND = {};

/*
 * Init sql connection pool
 * @param {Object} app The app for the server.
 */
NND.init = function(app){
	_pool = require('./dao-pool').createMysqlPool(app);
};

/**
 * Excute sql statement
 * @param {String} sql Statement The sql need to excute.
 * @param {Object} args The args for the sql.
 * @param {fuction} cb Callback function.
 * 
 */
NND.query = function(sql, args, callback){
	const resourcePromise = _pool.acquire();
	resourcePromise.then(function(client) {
		client.query(sql, args, function(err, res) {
			_pool.release(client);
			callback.apply(null, [err, res]);
		});
	}).catch(function(err){
		if(!!err){
			console.error('query error:',err);
		}
		callback(err);
	});
};

/**
 * Close connection pool.
 */
NND.shutdown = function(){
	_pool.drain().then(function(){
		_pool.clear();
	});
};

/**
 * init database
 */
sqlclient.init = function(app) {
	if (!!_pool){
		return sqlclient;
	} else {
		NND.init(app);
		sqlclient.insert = NND.query;
		sqlclient.update = NND.query;
		sqlclient.delete = NND.query;
		sqlclient.query = NND.query;
		return sqlclient;
	}
};

/**
 * shutdown database
 */
sqlclient.shutdown = function(app) {
	NND.shutdown(app);
};

3、配置一个MD5模块,正式应用里面账号密码肯定不能是明文的,我们加一个md5模块,虽然这里用不到,但是养成好习惯。

进入game-server,命令行 npm install md5。

4、完成前端服务器代码(至于gate代码在这个例子里直接用就好,不做改动)。客户端发起一个请求,客户端发给gate服务器,然后gate服务器给分配一个connector服务器(前端服务器),connector服务器接收客户端的连接请求,创建与客户端的连接,维护与客户端的会话(session)信息,同时接收客户端对后端服务器的请求,按照用户配置的路由策略,将请求路由给具体的后端服务器。当后端服务器要对客户端发消息时,connector也会完成对客户端的消息发送。

进入game-server/app/servers/connector/handler,打开entryHandler.js,完善代码。Handler.enter 负责维护客户端的session 包括建立绑定等,玩家进入后返回一个成功字段,并且分配session,uid为客户端名字

module.exports = function(app) {
	return new Handler(app);
};

var Handler = function(app) {
		this.app = app;
};

var handler = Handler.prototype;

/**
 * New client entry chat server.
 *
 * @param  {Object}   msg     request message
 * @param  {Object}   session current session object
 * @param  {Function} next    next stemp callback
 * @return {Void}
 */
handler.enter = function(msg, session, next) {
	var self = this;
	var rid = msg.rid;
	var uid = msg.name + '*' + rid
	var sessionService = self.app.get('sessionService');

	//duplicate log in
	if( !! sessionService.getByUid(uid)) {
		next(null, {
			code: 500,
			error: true
		});
		return;
	}

	session.bind(uid);
	session.set('rid', rid);
	session.pushAll();
	
	session.on('closed', onUserLeave.bind(null, self.app));

	//put user into channel
	self.app.rpc.chat.chatRemote.add(session, uid, self.app.get('serverId'), rid, true, function(users){
		next(null, {
			users:users
		});
	});
};

/**
 * User log out handler
 *
 * @param {Object} app current application
 * @param {Object} session current session object
 *
 */
var onUserLeave = function(app, session) {
	if(!session || !session.uid) {
		return;
	}
	app.rpc.chat.chatRemote.kick(session, session.uid, app.get('serverId'), session.get('rid'), function(){
		console.log("====== kick callback over! ======");
	});
};

5、完成后端服务器代码。在servers下新建game/handler/gameHandler.js。负责具体的购买逻辑,该服务不可直接和客户端通讯,也就是客户端pomelo.init 不能连接到后端服务器game。

var pomelo = require('pomelo');

module.exports = function(app){
	return new Handler(app);
}

var Handler = function(app){
	this.app = app;
}

//prototype属性使您有能力向对象添加属性和方法
var handler = Handler.prototype;

handler.getNotify = function(msg,session,next){	
//console.log(msg);
//console.log(session);	
	next(null,{msg:"welcome"+ msg.name + "enter the game"});
}

handler.buyGoods=function(msg,session,next){
	var id = msg.id;
	var count = msg.count;
	console.log("player uid: "+ session.uid);
		
	if(id=="100" && count ==1){
		var sql = "insert into goods (id,owner) values (?,?)";
		var args = [id, session.uid];
		//获取全局 mysql client
	 	var dbclient= pomelo.app.get('dbclient');
		
		console.log(dbclient);
	
		//执行sql语句,函数insert和query等效
		dbclient.query(sql, args, function(err, res){
			console.log('........................');
			console.log(err+'                 '+JSON.stringify(res));
			console.log('........................');
			if(err){
				//数据库操作失败
				next(null, {msg:'fail to buy', code:200});
			}else{
				//购买成功
				next(null, {msg: 'successful',code:200});
			}
		});		
	}else{
		//返回客户端调用
		next(null,{msg:"fail, code:200"});
	}	
}

6、配置servers.json和adminServer.json,把新增的game服务器加上。进入game-server/app/config。

{
    "development":{
        "connector":[
             {"id":"connector-server-1", "host":"127.0.0.1", "port":4050, "clientPort": 3050, "frontend": true},
             {"id":"connector-server-2", "host":"127.0.0.1", "port":4051, "clientPort": 3051, "frontend": true},
             {"id":"connector-server-3", "host":"127.0.0.1", "port":4052, "clientPort": 3052, "frontend": true}
         ],
        "chat":[
             {"id":"chat-server-1", "host":"127.0.0.1", "port":6050},
             {"id":"chat-server-2", "host":"127.0.0.1", "port":6051},
             {"id":"chat-server-3", "host":"127.0.0.1", "port":6052}
        ],
		"game":[
			{"id":"game-server-1", "host":"127.0.0.1","port":8000}
		],
        "gate":[
	       {"id": "gate-server-1", "host": "127.0.0.1", "clientPort": 3014, "frontend": true}
	    ]
    },
    "production":{
           "connector":[
             {"id":"connector-server-1", "host":"127.0.0.1", "port":4050, "clientPort": 3050, "frontend": true},
             {"id":"connector-server-2", "host":"127.0.0.1", "port":4051, "clientPort": 3051, "frontend": true},
             {"id":"connector-server-3", "host":"127.0.0.1", "port":4052, "clientPort": 3052, "frontend": true}
         ],
        "chat":[
             {"id":"chat-server-1", "host":"127.0.0.1", "port":6050},
             {"id":"chat-server-2", "host":"127.0.0.1", "port":6051},
             {"id":"chat-server-3", "host":"127.0.0.1", "port":6052}
        ],
		"game":[
			{"id":"game-server-1","host":"127.0.0.1","port":80000}
		],
        "gate":[
           {"id": "gate-server-1", "host": "127.0.0.1", "clientPort": 3014, "frontend": true}
        ]
  }
}
[{
    "type": "connector",
    "token": "agarxhqb98rpajloaxn34ga8xrunpagkjwlaw3ruxnpaagl29w4rxn"
}, {
    "type": "chat",
    "token": "agarxhqb98rpajloaxn34ga8xrunpagkjwlaw3ruxnpaagl29w4rxn"
},{
    "type": "gate",
    "token": "agarxhqb98rpajloaxn34ga8xrunpagkjwlaw3ruxnpaagl29w4rxn"
},{
	"type": "game",
	"token": "agarxhqb98rpajloaxn34ga8xrunpagkjwlaw3ruxnpaagl29w4rxn"
}
]

五、配置客户端。完成cocos creator客户端代码

1、直接建个helloWorld项目,在script文件夹下新建个pomelo文件夹,用来放pomelo 库,这个库的制作参见第二章标题3提到的帖子

2、在scipt文件夹下新建个test.js

cc.Class({
    extends: cc.Component,

    properties: {
     
    },

 
    onLoad: function () {
        pomelo.on('disconnect', function(reason) {
            console.log("pomelo.on() disconnect: ", reason);
        });
        
        var host = "127.0.0.1";
        var port = "3014";
        var gateRoute = 'gate.gateHandler.queryEntry';
        var uid="u001";
        var rid="01";
        var name="xiaoming";
        //请求链接gate服务器
        pomelo.init({
                host: host,
                port: port,
                log: true
                }, function(){
                //连接成功之后,向gate服务器请求ip和port    
                    pomelo.request(gateRoute,{
                        uid: uid
                    }, function(data){
                        //断开与gate服务器之间的连接
                        pomelo.disconnect();
                        //使用gate服务器返回的ip和port请求链接connector服务器
                        pomelo.init({
                            host: data.host,
                            port: data.port,
                            log: true
                        },function(){
                            //连接成功之后,向connector服务器发送登陆请求
                            var connRoute="connector.entryHandler.enter";
                            pomelo.request(connRoute,{name: name, rid:rid},function(data){
                                //登陆成功之后 显示登陆成功
                                cc.log(JSON.stringify(data));
                                console.log("登陆成功啦");
                                console.log("entry :" + data.msg);

                                var gameRoute="game.gameHandler.getNotify";
                                var buyRoute='game.gameHandler.buyGoods';
                                pomelo.request(gameRoute,{name:name},function(data){
                                    //测试后端服务器
                                    cc.log("client.js:"+JSON.stringify(data));
                                    console.log('测试后端服务器');
                                pomelo.request(buyRoute,{id:"100",count:1},function(data){
                                    cc.log('buy goods:'+JSON.stringify(data));
                                });
                                });
                            });
                        });

                    });
                pomelo.on('onChat', function(data) {
                    console.log(data.from, data.target, data.msg);
                });

        });

    },
    
    start () {

    },

    // update (dt) {},
});

六、运行测试。

用testConnection进入mysql,在webstorm中启动game-server(或者cmd,进入game-server文件夹下 pomelo start),然后运行cocos creator的项目。之后可以看到pomelo数据库中goods表里新增加了一条数据



你可能感兴趣的:(pomelo,mysql,cocos,creator)