Pomelo-完整的聊天服务搭建及遇到的坑

写在前面:欢迎大家与我交流讨论任何关于聊天服务开发有关的问题!!!

在阅读本文之前,你需要对pomelo的基本知识有所了解,可参考:

  1. Pomelo搭建(一)
  2. Pomelo搭建(二)
    注:这里所介绍的聊天服务是集成在Web应用中的一个模块,不是独立的聊天系统

一.添加身份验证(JWTToken)

在这里对用JWTToken进行简单的介绍:用户在登陆后获取到服务器返回的token(可理解为身份令牌),下一次请求时带上这个令牌进行身份验证,验证成功才可访问。且token有过期时间,在一定时间以内有效,超期后需重新登陆。
不了解JWTToken的可以到这里看看:JWTToken简介

注:以pomelo为基础的聊天服务器是基于websocket长连接的,因此只有第一次连接的请求是发送http请求(三次握手),后续调用根据route路由,故在例子中将token作为请求参数传到服务端进行身份验证,若有其他的更好的处理方法,欢迎交流讨论。

  1. JWTToken组成
    分为三部分:头部(header)、载荷(payload)、签证(signature)。
    (1)头部(header):包括两部分信息,a.声明类型(jwt) b.声明加密使用的算法(通常直接使用HmacSHA256)。如:{‘type’:‘JWT’, ‘alg’: ‘HS256’}
    (2)载荷(payload):存放有效信息的地方,可放置一些验证信息,如用户名等
    (3)签证(signature):由三部分组成,各部分之间由 " . " 连接
  • header经过base64后生成的字符串,记为 headerStr
  • payload经过base64后生成的字符串,记为 payloadStr
  • signature则是由 headerStr + '.' + payloadStr经过header中声明的加密方式进行secret组合加密后的字符串,记为 sigStr

JWTToken = headerStr + ‘.’ + payloadStr + ‘.’ + sigStr
注:JWTtoken 各部分JSON对象中的属性顺序不可调换

  1. Filter的添加
    为了能对每一个请求进行身份验证,我们添加filter在每一个请求中的token进行验证。下面来讲讲pomelo中是如何添加filter的:
    在pomelo的一篇开发文档中介绍了一个脏话替换的filter的小例子,在这里对这个小例子进行简单的介绍和分析。
    我们先创建一个filter:Filter.js(game-server/app/servers/chat/filter/)
module.exports = function(){
    return new Filter();
}

var Filter = function(){};
// 前置filter,在请求之前进行处理
Filter.prototype.before = function(msg, session, next){
	// 获取请求的参数:content表示发送的消息,token即为请求的token
	var content = msg.content;
	var token = msg.token;
	// 进行token验证,判断token是否正确以及是否过期
	if(validate(token)){
	    // 验证成功,对content进行处理,处理后参数会传到对应接口
	    msg.content = content.replace('fuck', '****');
	    // next() 表示filter处理结束,下一步会转到对应请求的handler中
	    next();
	}
	// token验证失败,在msg中放置错误信息,如:
	msg.code = 500;
	msg.errorMsg = 'token错误或token过期';
	next();
}
// 后置filter,在请求结束后进行处理
Filter.prototype.before = function(msg, session, next){
	// 根据业务需要进行添加处理,略...
}

创建好filter后,在app.js中引入Filter.js,并如下配置:

var pomelo = require('pomelo');
var routeUtil = require('./app/util/routeUtil');
/**
 * Init app for client.
 */
var app = pomelo.createApp();
app.set('name', 'chatofpomelo');
// 对所有的connector服务器进行配置
app.configure('production|development', 'connector', function(){
	app.set('connectorConfig',
		{
			connector : pomelo.connectors.hybridconnector,
			heartbeat : 3,
			useDict : true,
			useProtobuf : true,
			closeTimeout : 60 * 1000,
		});
});
// 对所有的gate服务器进行配置
app.configure('production|development', 'gate', function(){
	app.set('connectorConfig',
		{
			connector : pomelo.connectors.hybridconnector,
			useProtobuf : true,
			closeTimeout : 60 * 1000,
		});
});

// 引入创建的Filter.js
var Filter = require('./app/servers/chat/filter/Filter');

// app configure,该配置表示在所有的服务器中都生效
app.configure('production|development', function() {
	// route configures
	app.route('chat', routeUtil.chat);
	// 使用Filter,before表示前置,after表示后置
	app.before(Filter);
});

// start app
app.start();

process.on('uncaughtException', function(err) {
	console.error(' Caught exception: ' + err.stack);
});

注:在此filter中,把处理的结果在真正的业务处理接口,即chat/handler中进行判断,错误则直接返回到前端服务器。(未找到直接在filter中返回错误到前端服务器的方式,如有更好的方案,欢迎交流学习)


二.日志记录

pomelo通过封装log4js,形成了pomelo-logger这个组件,因而使用日志记录时需引入这个组件。为了能够更好的理解log4js的处理,在本文中对直接使用log4js进行介绍。

  1. 安装log4js----- npm install log4js
  2. 配置log4js,新建log4js.js文件
// 引入log4js对象
var log4js = require('log4js');
// 配置日志内容
log4js.configure({
	appenders: {
        console: {
            type: "console"
        },
        dateFile: {
            type: "dateFile",
            // 生成日志的保存路径,该路径表示日志保存到项目目录下的logs文件夹
            filename: "logs/LogFile",
            pattern: "-yyyy-MM-dd.log",
            category: "log_date",
            encoding: 'utf-8',
            alwaysIncludePattern: true
        }
    },
    categories: {
        dateFile: {
            appenders: ['dateFile'], level: 'error'
        },
        default: {
            appenders: ['console', 'dateFile'], level: 'all'
        }
    }
});
var dateFile = log4js.getLogger('log_date')

module.exports = dateFile

使用时可通过: var log = require(‘创建的log4js.js文件’);
通过log.error();log.info();log.warn()等输入不同级别的日志信息。
关于log4js的详细介绍,可查看:log4js及其API


三.相关部署及遇到的问题

运行环境:AWS云服务器(EC2)

步骤:
1.搭建环境:安装node(建议使用nvm进行安装)、安装python、安装pomelo(npm install pomelo -g)
2.拉取代码:git clone https://github.com/NetEase/chatofpomelo.git
(以chatofpomelo为例)
3.运行项目目录下的npm-install.sh脚本安装相关依赖
注:若遇到安装权限问题,可对相关错误的文件及文件夹使用(sudo chown -R 当前登录用户名 filePath)修改权限
4.pomelo start -e production -D 运行服务(-e为选择环境,-D表示后台运行)

问题:
1.启动后访问报错 ParserIncomingMessage is not a constructor.
解决:node版本太高,选择较低的版本重装后再从步骤3开始。
注:本人使用的node版本为 v6.11.2,报错的node版本为 v10.x.x

2.关于host地址的设置(暂未使用pomelo的集群配置,故host均为同一IP)
game-server/config下的master.jsonservers.json中,将其中的host改为对应服务器的公网IP.

以上是对pomelo使用的一些记录,若有任何错误的地方,欢迎指正,也希望能和大家一起交流学习,共同进步。

你可能感兴趣的:(Nodejs)