搬服务端的体会--接着来。
上一篇 说了问题。现在说说重构后的构架。
基于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的第一个就行。
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行屏蔽掉而已。
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
消息队列只传递指针,意思就是某个消息由接收方alloc,然后msgsnd这块内存的指针,msgrcv收到这个指针,处理完了free掉,而不是整个消息放进去。
1
struct
mymsg {
2 long int mtype; /* message type */
3 char mtext[ 4 ]; /* message text */
4 }
5
说实话当初在msgsnd msgrcv上调试了很久
2 long int mtype; /* message type */
3 char mtext[ 4 ]; /* message text */
4 }
5
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 )
然后死活提示参数不正确。。。
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口物理破坏。。。囧。。。当然,我要起带头作用,忍。。。