gfirefly 框架分析

数据包

协议

协议如下表
| HEAD_0 | … | HEAD_3 | protoVersion | serverVersion | length |
|——–|——–|——–|——–|——–|——–|
| char | … | char | int | int | int |
gfirefly框架是基于TCP协议的长连接,框架中没有使用keep-alive,那么网络异常断开(如网线突然拔掉)的时候,应用层是不知道,当我们自己使用的时候就必须加心跳包等机制来解决这个问题。另外数据加密没有放到协议层,那么需要加密数据只能在打包数据之前使用加密算法。

黏包

gfirefly中对底层的数据包进行了黏包处理,如上表所示,协议头定义了length,此时应用层就知道什么时候结束单个包的传输。见gfirefly/netconnect/protoc.py line 43:

def dataReceived(self, data):
    length = self.factory.dataprotocl.getHeadlength()#获取协议头的长度
    self.buff += data
    while self.buff.__len__() >= length:
        unpackdata = self.factory.dataprotocl.unpack(self.buff[:length])
        if not unpackdata.get('result'):
            log.msg('illegal data package --')
            self.factory.connmanager.loseConnection(self.transport.sessionno)
            break
        command = unpackdata.get('command')
        rlength = unpackdata.get('length')
        request = self.buff[length:length+rlength]
        if request.__len__()< rlength:
            log.msg('some data lose')
            break

网络

gfirefly 是由firefly修改而来,那么当底层网络模块由twisted 更换为 gevent的时候,加入了一个叫gtwisted的wrapper。实际上还是使用的gevent.StreamServer。还有一些用不爽的地方,而且一直没有修改,比如gtwisted/core/base.py line 122左右, getHost函数 手动返回"0.0.0.0"什么的。

rpc

| length | data |
|——–|——–|
| int | string |
rpc的协议头如上表,其中data为dict经marshal的结果,marshal速度还算可以,我测试中marshal和msgpack速度不相上下,但是msgpack可以跨平台,呵呵。data的内部是这样的:{'_msgtype': _msgtype, '_key': _key, '_name': _name, '_args': args, '_kw': kw},看样子没什么特别之处。

分布式

gfirefly中实现了rpc的双向调用,使之实现分布式更容易一下。不过我测试双向RPC的效率却很低,qps大概在4000左右,而测试单向的mprpc qps达到1W8.

  1. gate节点为中心节点。
  2. 有child节点连接到gate,child之间相互通讯也是通过gate节点来中转。

缓存

框架封装了一个使用memcache的来缓存mysql数据的模块,数据查询仅限于有主键或者外键的表,不过也已经足够。不足的地方在于value保存的是一个很大的字典,每次调用修改一个字段的时候,需要修改存储的整个value,这样效率比较低。如果用redis的hset会好很多,另外我自己对比测试redis驱动和memcache驱动。结果如下

| redis-py | credis | memcache | pylibmc |
|——–|——–|——–|
| 2W+ | 4W+ | 2W+ | 5W+ |
补充:credis没有封装对命令的函数。

gevent中的坑

模拟大量登录时,程序变慢。官方的mysql采用的是mysql-python(底层是c/c++),在所有mysql驱动中算是很快的了,比umysql慢点,不过umysql不兼容DB-API 2.0。测试的时候gevent在调用里面查询的时候被阻塞住。之后用豆瓣的greenify并没有成功,最终换成了pymysql。memcache驱动换成了pylibmc,memcache足够快了,如果再用gevent只会拖慢速度,搜索得出的结果是gevent中会有大量的系统调用,==亚毫秒级不推荐用greenlet==。

万物归一

使用场景分析:这个框架只适用于一些简单的(游戏)服务器应用。python用起来很爽,不过速度是一个很大的问题,即使使用各种黑科技,可能也不尽人意啊,毕竟很多游戏服务器是 同时I/O和CPU密集的。

你可能感兴趣的:(GFirefly,Firefly,gevent)