服务器端软件的复杂度相对比较高。30000多行代码的中间件软件的主线程程序又是怎样的呢?
小鸡射手在实际工作中设计的网络服务的主线程代码如下:
IContext
&
context
=
ContextManager::GetContext();
IEventHandler & handler = EventHandlerManager::GetEventHandler();
while ( ! IsStopped())
... {
IEvent* event = context.eventQueue.GetEvent(context.configSetting.eventQueueTimeout);
if(event==0) continue;
...{
const auto_ptr<IEvent> pEvent(event);
try
...{
event->Handle(handler, context);
}
catch(const exception& ex)
...{
context.logger.Error("Dispatcher中发现异常:[%s]。", ex.what());
}
catch(...)
...{
context.logger.Error("Dispatcher中发现未知异常。EventID is [%s]", event->GetInfo());
}
}
}
IEventHandler & handler = EventHandlerManager::GetEventHandler();
while ( ! IsStopped())
... {
IEvent* event = context.eventQueue.GetEvent(context.configSetting.eventQueueTimeout);
if(event==0) continue;
...{
const auto_ptr<IEvent> pEvent(event);
try
...{
event->Handle(handler, context);
}
catch(const exception& ex)
...{
context.logger.Error("Dispatcher中发现异常:[%s]。", ex.what());
}
catch(...)
...{
context.logger.Error("Dispatcher中发现未知异常。EventID is [%s]", event->GetInfo());
}
}
}
这段代码应该还是比较好理解的,eventQueue采用stl queue加上线程同步机制实现。其中涉及到的两个关键接口定义如下:
class
IEvent
...
{
public:
virtual ~IEvent() ...{}
virtual void Handle(IEventHandler& handler, IContext& context)=0;
virtual const char* GetInfo()=0;
} ;
class IEventHandler ... {
public:
virtual ~IEventHandler() ...{}
virtual void Handle(ThisEvent& event, IContext& context)...{}
virtual void Handle(ThatEvent& event, IContext& context)...{}
virtual void Handle(OtherEvent& event, IContext& context)...{}
}
public:
virtual ~IEvent() ...{}
virtual void Handle(IEventHandler& handler, IContext& context)=0;
virtual const char* GetInfo()=0;
} ;
class IEventHandler ... {
public:
virtual ~IEventHandler() ...{}
virtual void Handle(ThisEvent& event, IContext& context)...{}
virtual void Handle(ThatEvent& event, IContext& context)...{}
virtual void Handle(OtherEvent& event, IContext& context)...{}
}
设计的灵感来自于:
-
Windows的消息机制。早期的Windows开发主程序就是GetMessage和switch循环,所以以上程序只是对此思想的Object Oriented版本;
-
Think in Java对垃圾分类的讨论,垃圾分类问题可以通过Visitor模式解决。下面就是采用该模式实现的具体event类的Handle方法。应用逻辑则是在IEventHandler的子类中实现。
void
ThisEvent::Handle(IEventHandler
&
handler, IContext
&
context)
... {
handler.Handle(*this, context);
}
... {
handler.Handle(*this, context);
}
该设计的优点是:
-
尽管服务器端的软件往往是多线程的,需要线程间同步。但是由于该设计的处理均在主线程上完成,故eventHandler中不需要(或者减少了大量)同步;
-
软件扩展容易,只要加event和对应的eventhandler;
-
code on interface,代码接口和实现分离,易于维护。
当然,该设计也有需要注意的地方:
-
eventHandler中的操作不允许blocking,所以类似写日志这样的操作实际上是放到后台线程完成的。 其中的原因和界面处理程序中长时间操作会导致界面没有反应一样;
-
理论上,该设计在多CPU的机器上,可能不能完全发挥硬件的潜力。
总之,这还是不错的设计。小鸡射手已经成功将它运用到公司的两大产品中。