posts - 18,  comments - 21,  trackbacks - 0
以前的服务端是win32平台,STLport-5.1.4,boost-1.34.1,asio-0.3.8,apr的内存管理,消息池用的是MSMQ。
构架是loginserver,accountdb,gate,gamedb,gameserver,数据流向是:帐号密码->loginserver->accountdb->loginserver->client->选区->gate->gamedb->gate->client->选人->gate->gameserver

先说说现在的问题,win32平台就不说了^_^,也不谈stlport boost的效率问题,msmq也中规中矩,主要是apr的问题,使用的是这样的形式来做的内存管理
 1 struct cUser
 2 {
 3     apr_pool_t* pool;
 4     
 5     char name[25];
 6     ushort level;
 7     
 8 };
 9 
10 // 申请
11 apr_pool_t* pool = 0;
12 apr_pool_create(_mainpool, &pool);
13 cUser* user = (cUser*)apr_pcalloc(pool, sizeof(cUser));
14 user->pool = pool;
15 strcpy_s(user->name, "test");
16 user->level = 0;
17 
18 // 释放
19 if (user)
20 {
21     if (user->pool)
22         apr_pool_destory(user->pool);
23 }

服务端运行过程中很偶尔会出现user->pool为空,因为释放是程序结束时统一释放,所以没有理由怀疑释放错误,只能是内存越界,比如

1 apr_pool_t* pool = 0;
 
2 apr_pool_create(mainpool, &pool);
 
3 
 
4 cUser* user = (cUser*)apr_pcalloc(pool, sizeof(cUser) * 20);
 
5 
 
6 for (int i = 0; i < 20; i++)
 
7     user[i].pool = pool;
 
8 
 
9 // 这只是个示例,当然不会有人这么做
10 // 假设cUser最后一个变量是 char temp[100];
11 struct cUser
12 {
13     apr_pool_t* pool;
14 
15     char name[25];
16     ushort level;
17     char temp[100];
18 };
19 memcpy(user[0].temp, "test"104);
20 // 这个时候user[1]的pool就是空的了。

因为构架是我做的,具体逻辑不是我写的,在几十万行代码里一点一点跟哪里出错实在太渺茫,而且有点怀疑apr内部是否有bug,因为看错误的内存,明显整个user都是被apr_pool_destroy掉的。so。。这次不用apr了,那么大个库使用一个apr_pool是有点杀鸡牛刀的感觉。

这次简简单单定义
void* mem_alloc(size_t size);
void* mem_realloc(void* p, size_t size);
void mem_free(void* p);

// 实现
void* mem_alloc(size_t size)
{
    
void* p = 0;
    p 
= malloc(size);

#ifdef _DEBUG
   
if (p)
        memset(p, 
0, size);
#endif
    
return p;
}

void* mem_realloc(void* p, size_t size)
{
    
void* p = 0;
    p 
= realloc(p, size);

    
return p;
}

void mem_free(void* p)
{
    
if (p)
    {
        free(p);
        p 
= 0;
    }
}


当然后面打算带上gc,暂时直接申请内存方便valgrind挑错。


构架的问题就大了,一开始的设计是单loginserver多gate,单gate对单gameserver,后来发现一个gameserver带30几张地图,跑5000+npc简直就是自残,于是改,改单gate带多gameserver,问题来了,我们的构架是gamedb只和gate联系,一旦跨地图组队,user信息就要从一个gameserver带到gate再发给另一个gameserver,以前只考虑了由gate保存user信息,gameserver只是一份copy,更新数据方便,但是现在gate的负担超级重。

还有数据库问题,用的oracle,oci直接操作,accountdb没问题,gamedb是来了请求就去数据库拿或者写,没有做user的缓存,而且是整个user结构体带来带去,通信量特别大。结果是经常报告statement操作的游标过多,提高oracle的64个游标数量只是暂时解决方案。经常选了服就卡住,拿不到人物信息。

最主要就是msmq轮询取消息process的时候没有用阻塞模式(或者没有阻塞模式?)
1 if (0 == MSMQGetMessage())
2 {
3     Sleep(1);
4 }
5 else
6 {
7     Process_Packet();
8 }

问题出在这个sleep(1)上了,不sleep,4个msmq线程,npc的process被抢的什么都干不成,sleep的话cpu就死活利用不上去。懒得找msmq的阻塞模式了。

还有就是设计上的问题了,比如
1 struct User_Save_Info
2 {
3     char name[25];// 没问题,12个中文字的名字。
4     int gender;// 性别,大哥,你有42亿种性别么?
5     int facestyle;// 脸型,同上
6     int hairstyle;// 发型,同上
7     // 后面类似的不说了。
8 };

我就说策划大哥们,我为了省包头的2字节绞尽脑汁,你们可好。。。无语了。。。

Item_Info_Save是存装备的,我们的装备有随机属性,但是他们居然把装备的通用属性都由服务器来发,最郁闷的是设计npc死亡掉落物品数量达到50件。。。就是一个npc死亡,我需要发8(小队人数)*50(装备个数)*sizeof(Item_Info_Save)(这个sizeof至少100字节)。。。

ok问题暂时说到这里,下一贴说重构后的改动。
posted on 2008-04-09 00:01 大日如来 阅读(2382) 评论(10)  编辑 收藏 引用 所属分类: 游戏-编程

FeedBack:
# re: 本次服务端搬平台的一些体会。
2008-04-09 09:14 | 梦在天涯
高深啊!  回复  更多评论
  
# re: 本次服务端搬平台的一些体会。
2008-04-09 09:15 | Kevin Lynx
这些东西“构架是loginserver,accountdb,gate,gamedb,gameserver,数据流向是:帐号密码->loginserver->accountdb->loginserver->client->选区->gate->gamedb->gate->client->选人->gate->gameserver” 吸收了

还有这个“memcpy(user[0].temp, "test", 104);“,加一个set_temp成员函数进去,这样的话虽然安全很多,只是不知道cUser是否还是个POD结构(不带vtable,应该还是可以默认地copy吧?)  回复  更多评论
  
# re: 本次服务端搬平台的一些体会。
2008-04-09 10:27 | zhiyong
1 struct User_Save_Info
2 {
3 char name[25];// 没问题,12个中文字的名字。
4 int gender;// 性别,大哥,你有42亿种性别么?
5 int facestyle;// 脸型,同上
6 int hairstyle;// 发型,同上
7 // 后面类似的不说了。
8 };

可以改用 bit fields,例子(from msdn):
struct
{
unsigned short icon : 8;
unsigned short color : 4;
unsigned short underline : 1;
unsigned short blink : 1;
} screen[25][80];

参考msdn 的: c / c++ bit fields   回复  更多评论
  
# re: 本次服务端搬平台的一些体会。
2008-04-09 12:09 | wangjs720
struct
{
unsigned short icon : 8;
unsigned short color : 4;
unsigned short underline : 1;
unsigned short blink : 1;
} screen[25][80];

这个结构好像没对齐啊  回复  更多评论
  
# re: 本次服务端搬平台的一些体会。
2008-04-09 12:52 | Matthew

struct
{
unsigned short icon : 8;
unsigned short color : 4;
unsigned short underline : 1;
unsigned short blink : 1;
} screen[25][80];

参考msdn 的: c / c++ bit fields
c / c++ bit fields 应该是有bigendian和littleendian问题的,还是慎用。  回复  更多评论
  
# re: 本次服务端搬平台的一些体会。
2008-04-09 14:51 | 饭中淹
架构有严重问题......
  回复  更多评论
  
# re: 本次服务端搬平台的一些体会。[未登录]
2008-04-09 16:37 | noname
sleep(1)
换成sleep(0)试试  回复  更多评论
  
# re: 本次服务端搬平台的一些体会。
2008-04-09 19:36 | Kevin Lynx
@饭中淹
问题是?  回复  更多评论
  
# re: 本次服务端搬平台的一些体会。
2008-04-09 22:51 | 大日如来
@Kevin Lynx
我想表达的意思只是处理第一个user的时候地址越界,把第二个user的pool置空,这种错误经常发生,比如我就干过这样的。

#define MAX_USERNAME 25

struct cUser
{
char name;
...
};

cUser* user = (cUser*)malloc(sizeof(cUser));
user->name = (char*)malloc(sizeof(MAX_USERNAME));

这样申请第一个user没问题,第二个就报错,调用堆栈不会显示sizeof(MAX_USERNAME)这种低级错误。要跟出来只能靠经验了。  回复  更多评论
  
# re: 本次服务端搬平台的一些体会。[未登录]
2008-05-08 02:32 | pass86
做游戏的所。  回复  更多评论
  

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理



<2008年5月>
27282930123
45678910
11121314151617
18192021222324
25262728293031
1234567

常用链接

留言簿(2)

随笔分类

随笔档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜