终于从欢跃数码出来了。离开了成都。
这边很迅速的办好了各种手续,房子也租上了,白菜也搬过来了。东西还没有寄到,主要是车,可能老马都还没给寄。
有点流水账的感觉了。。。其实这段时间事情太多了。也算了经历了人生一大转折,正式转型到管理层了。有很多想法。慢慢来。
在装新的工作机。卡位暂时安排在程序这边。
装补丁要重启机器了。下次慢慢写。
posted @
2009-10-12 13:00 大日如来 阅读(267) |
评论 (0) |
编辑 收藏
比如我开了2个终端,ttyp1空着,在ttyp2上gdb loginserver跑起来之后,who看有ttyp1和ttyp2,ttyp1上有bash,sshd,ttyp2上有bash,sshd,gdb,loginserver。
我关了ttyp2,再看who只有ttyp1了,ttyp2上的bash和sshd没了,但是gdb和loginserver还在,假如我kill掉loginserver,gdb也会跟着关掉,我现在想要gdb和loginserver重新回到ttyp1的控制里,感觉上就是从ttyp1的STDIN里读,往ttyp2的STDOUT里写,怎么做?
gettty貌似有这个功能,但是他不算是一个utility tools,watch可以,带-W参数还可以写,但是需要root权限,而且还是和接管这种感觉差了一点,因为我对服务器管理实在很差,哪位看到了知道怎么做可以留言给我,不甚感激。
posted @
2008-05-12 01:26 大日如来 阅读(1394) |
评论 (1) |
编辑 收藏
又是一个月没写BLOG了,这一个月回家基本都不怎么碰电脑,更换平台也一段时间了,FreeBSD留给我的印象最大的是稳定,其次是反应很干脆,比如程序有什么BUG,直接SIGSEGV,比如:
int a = 5;
printf("%s", a);
这个在WIN32平台上只可能是未知结果,FreeBSD就报了错误。
还有就是FreeBSD和WIN32的内存管理完全是2个极端,WIN32在物理内存闲置的时候都占用了一半的虚拟内存,而FreeBSD仅仅是在物理内存被吃完,留下512K开始使用虚拟内存。
个人感觉,这样的区别是来自一个做桌面,一个做服务,做桌面的总有一些慢轮询需要处理,比如图标的cache啊,各种状态的保存啊,很占内存的东西,但是又不是实时的使用,留在物理内存里纯属浪费,而FreeBSD一开始设计的时候根本没有图形界面,纯纯一个terminal,需要的东西内核都帮你做了,你可以随意开关你认为必要不必要的东西,所以FreeBSD做服务端非常合适的。
终于还是把GC加到了服务端里面,mapserver内存从960M涨到了1560,效率上没怎么测试,稳定性感觉略微有点下降,好处可能要在实际应用中才能体会了。
posted @
2008-05-12 01:23 大日如来 阅读(289) |
评论 (0) |
编辑 收藏
快到都江堰叻
从都江堰包车到青城后山
早饭+男女配角
农家乐后得小溪
早上准备爬山叻
男女配角全面登场
开始上山叻
体力很充沛,还可以拍风景
某猛男中招,拉肚子叻
刚开始走就吃!
嘎嘎
个性男
上主题,哇哈哈哈哈
实际上大部分路都在推和抗
还有体力拍风景
背包跑到某男身上去叻。。汗一个。
某男开始执掌相机
真得很耗体力。。。
到叻山脚至半山得缆车
又一村,我得车车止步于此。。。实在可惜。
我得体力透支,艰难得在往上爬
还好没抗车上来,万佛洞得栈道实在BT
天王殿门口,目标在望
多谢2位帅哥一路陪我
下又一村做得缆车,45,贵就一个字。。。
又一村取上车,因为还要骑回成都,本来打算继续做缆车,结果被告知要排至少2个小时队
一咬牙一跺脚,推下山
相机被某男拿走,没得照片叻。
回到后山,居然轻松爬上回去得半山,然后放坡57到前山。
都江堰一顿30晚饭。
吃到天黑,摸黑30码拉回成都。
到家10:30不到。
最后总结。。抗车上山是个很拉风很自虐得行为。
准备上山得路上旁边卖黄瓜得都在说 小伙子,车子上不去得。
半路上不断有人嘀咕,自行车怎么上得山
上了山只想爽快得吼出来。
其实我也不太懂怎么会抗车上山,一开始只是退了农家乐得房子,寄存下来不放心,爬叻一截就只剩一个想法,一定要上去。
posted @
2008-05-12 00:38 大日如来 阅读(269) |
评论 (0) |
编辑 收藏
上一篇 说了问题。现在说说重构后的构架。
基于freebsd6.3 boost-1.35.0(多处升级,最重要是包含了asio,升级了thread) STLport-5.1.5 消息队列(msgget,msgsnd,msgrcv)
构架方便借鉴了部分
云风的思路。
loginserver,gate,gamedb,postoffice,mapserver
accountdb去掉了,整合进loginserver里,loginserver直接连oracle,取列表信息后去连gate,gate连gamedb负责发人物列表
家里机器只有画图。。。忍着看吧。。。
下面开始都是一个服为一个单位。
一个服的gate是可以随时开关的,gate起来的时候会给loginserver和postoffice注册
1 struct GateInfo
2 {
3 char name[25];
4 char ip[16];
5 short port;
6 uint online;
7 };
8
9 typedef vector<GateInfo*> VecGateInfo;
10 VecGateInfo _gateinfo;
11
12 // 当有用户连上或者断开gate时
13 sort(_gateinfo.begin(), _gateinfo.end(), GateSort)
14
15 // 这样client取gate信息的时候只需要发给每个gate_group的第一个就行。
gamedb是所有userinfo的集结地,有缓存,只在第一次请求的时候把userinfo读进缓存,其余时刻都是写,一个慢线程,5分钟轮询写一遍,某个user更新发给gamedb,由gamedb负责通知其他拷贝同步更新。
mapserver实际上是一堆服务端的组合总称,这块来自云风的构架,分为chatserver(聊天服务端),mapserver(地图服务端,还可以区分为只带功能性npc地图,或者称为非pk地图,和其他地图),guildserver,dropserver。。。每个server都和postoffice连接,并且按功能和gamedb和其他服务端连接,按功能划分具体的服务端可以很好的把逻辑分散,不会导致某个模块的bug整个服务端的崩溃,在程序员整体调试水平不高的情况下,大大降低出错后分析的难度。
相比较以前来说就是gamedb后移,数据重心放在gamedb上,只读一次的做法要严格保证gamedb的效率和稳定,否则会死的很抽象。
一些细节mark下来,boost+asio在freebsd上居然不用kqueue用的是select。。。Orz,这是我在一次单步跟一个内存错误发现的
1 //
2 // kqueue_reactor_fwd.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2008 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 // Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)
7 //
8 // Distributed under the Boost Software License, Version 1.0. (See accompanying
9 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 //
11
12 #ifndef BOOST_ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP
13 #define BOOST_ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP
14
15 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
16 # pragma once
17 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
18
19 #include <boost/asio/detail/push_options.hpp>
20
21 #if !defined(BOOST_ASIO_DISABLE_KQUEUE)
22 #if defined(__MACH__) && defined(__APPLE__)
23
24 // Define this to indicate that epoll is supported on the target platform.
25 #define BOOST_ASIO_HAS_KQUEUE 1
26
27 namespace boost {
28 namespace asio {
29 namespace detail {
30
31 template <bool Own_Thread>
32 class kqueue_reactor;
33
34 } // namespace detail
35 } // namespace asio
36 } // namespace boost
37
38 #endif // defined(__MACH__) && defined(__APPLE__)
39 #endif // !defined(BOOST_ASIO_DISABLE_KQUEUE)
40
41 #include <boost/asio/detail/pop_options.hpp>
42
43 #endif // BOOST_ASIO_DETAIL_KQUEUE_REACTOR_FWD_HPP
反正我只是不负责任的把22和38行屏蔽掉而已。
消息队列只传递指针,意思就是某个消息由接收方alloc,然后msgsnd这块内存的指针,msgrcv收到这个指针,处理完了free掉,而不是整个消息放进去。
1 struct mymsg {
2 long int mtype; /* message type */
3 char mtext[4]; /* message text */
4 }
5
说实话当初在msgsnd msgrcv上调试了很久
1 char* packet;// 假设这个packet包括了传进来的包
2 mymsg* msg = (mymsg*)mem_alloc(sizeof(mymsg));
3 memcpy(msg->mtext, &packet, sizeof(char*));
4 msgsnd(msgid, msg, sizeof(char*),0)
然后死活提示参数不正确。。。
逐字逐句读了man msgsnd数十遍之后发现。。。问题在msg->mtype不能等于0
ok,公司物理断网,usb口物理破坏。。。囧。。。当然,我要起带头作用,忍。。。
posted @
2008-04-09 22:42 大日如来 阅读(2329) |
评论 (2) |
编辑 收藏
以前的服务端是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 @
2008-04-09 00:01 大日如来 阅读(2435) |
评论 (10) |
编辑 收藏
系 统 |
配 件 |
型 号 |
价 格 |
备 注 |
车身 |
车架 |
BIGCAT COMPLITE |
¥450 |
|
前叉 |
SUNTOUR XCR |
¥640 |
油压线控锁 |
立管 |
UNO四钉 |
¥40 |
|
副把 |
|
|
|
把横 |
X MISSION直把 |
¥20 |
|
把套 |
PRO TEN |
¥25 |
|
碗组 |
|
|
|
坐管 |
ZOOM全铝 27.2 |
¥30 |
无标 |
坐垫 |
WTB SPEED V COMP |
¥230 |
|
坐夹 |
铝合金快拆 |
¥10 |
|
车首垫环 |
SCOTT铝合金 |
|
|
传动 |
牙盘 |
SHIMANO M440 9S |
¥230 |
|
中轴 |
清豪CH52轴承 |
¥30 |
|
脚踏 |
FPD NWL90 |
¥45 |
|
飞轮 |
SRAM PG950 |
¥130 |
|
链条 |
SHIMANO HG73 |
¥60 |
|
轮组 |
花鼓 |
QUANDO 昆腾滚珠碟刹 |
¥150 |
|
车圈 |
ALEX DP20碟刹专用 |
¥150 |
|
钢丝 |
电镀黑不锈钢 |
¥35 |
|
胎垫 |
XXF尼龙高压 |
¥20 |
|
内胎 |
KENDA建大 |
¥20 |
|
外胎 |
建大26*1.95 |
¥60 |
|
变速 |
指拨 |
SHIMANO DEORE M510 |
¥230 |
|
前拨 |
SHIMANO DEORE M510 |
¥130 |
|
后拨 |
SHIMANO XT M760 |
¥320 |
|
制动 |
刹把 |
AVID FR5 |
¥85 |
|
夹器 |
HAYES MX1 |
¥350 |
|
碟片 |
|
|
|
其他 |
马表 |
SIGMA BC906 |
¥100 |
|
前灯 |
|
|
|
尾灯 |
MC18 |
¥20 |
|
链贴 |
SHIMANO XTR |
¥5 |
|
水壶 |
|
|
|
水壶架 |
闪电铝合金 |
¥10 |
|
货架 |
|
|
|
全车线 |
JAGWIRE套装 |
¥20 |
|
总价 |
|
|
¥3,645 |
|
posted @
2008-03-18 17:33 大日如来 阅读(534) |
评论 (1) |
编辑 收藏
一开始是这样,某个程序在debug模式下写的一段附魔效果的代码,测试正常后提交。
我这里release编译,F5测试了没问题。提交测试人员后被告知没有附魔效果。我继续F5测试没任何问题,和测试人员争执后发现。。。
如果用挂着调试器没有任何问题,直接双击exe就是没有效果。
最后发现是一个变量没有在类构造的时候初始化。
是一个bool类型的变量,问题是,为什么挂这调试器这个变量就是true,直接双击exe这个变量就是false???
posted @
2008-03-18 17:22 大日如来 阅读(2126) |
评论 (6) |
编辑 收藏