请选择 进入手机版 | 继续访问电脑版

NoahFrame

 找回密码
 Register Now
搜索
热搜: redis mysql tutorial
查看: 2969|回复: 4

第八章 NF分布式服务器解决方案--并行运算

[复制链接]

30

主题

111

帖子

632

积分

Administrator

Rank: 9Rank: 9Rank: 9

积分
632
发表于 2016-12-30 11:19:05 | 显示全部楼层 |阅读模式
NF(https://github.com/ketoo/NoahGameFrame)全称为 NoahFrame/NoahGameFrame。


NF最早为客户端设计,后来随着时代的变化,而为自己又转为服务器开发,故在吸收了众多引擎的优点后(包含Ogre的插件模式&模块化管理机制,Bigworld的数据管理&配置机制,类似MYGUI的接口层次设计),经过多年演化和实践,变成了一套游戏开发J解决方案。方案中包含开源的服务器架构,网络库(站在libevent的肩膀上),和unity3d的demo源码。现在NF已经在多个公司的多个项目中使用,其中包含知名产品 《全民无双》。


关键词


NoahGameFrame/NoahFrame/NF
集群/负载均衡/分布式
网关服务器 GateServer 心跳 多线程/线程池 开源网络框架/模型
一致性hash算法/ConsistentHash
游戏开发中的设计模式/数据结构
Socket Nagle/粘包/开源游戏服务器/ Game Server






先进计算机拥有大量的计算单元(CPU),如何尽可能有效利用这些计算单元来解决业务设计中的瓶颈,成为一个新的设计难题。
传统的开发过程中,使用多线程来进行业务开发,在使用过程中,颇多问题,比如数据加锁问题,调试麻烦,出现问题难于定位等,都限制了多线程的在业务中的广泛使用。因此很多人转而使用多进程,从架构上进行业务分离从而使用更多的计算资源。

在其他语言中,多少有一些现成的特性或者知名的库来处理列如异步/无状态密集计算形的任务。
而在C++中也有知名库Theron来提供并行编程的Actor处理模式,可以解决多线程开发中的各种痛处,提供了一种新的开发思路。NF就是使用Theron封装成新的Actor模式来处理大量的异步业务,比如耗时的数据存储/加载,http等业务(新版本的Theron增加了对夸机器计算资源的利用,简直是如虎添翼)。

Actor开发,就是对并行程序的简单的、高级别的抽象,它提供异步、非阻塞、高性能的事件/消息驱动编程模型(代码可以异步处理请求并采用独占的方式执行非阻塞操作),相比使用线程来解决业务问题,它是非常轻量的事件驱动处理。

在Actor编程模式中,一切均为Actor,各Actor之间通过消息相互传递数据(屏蔽了线程细节),各Actor可以同时利用CPU处理自己的业务,可以方便的做到真正的“并行计算”(虽然底层也是利用的线程池等调度,但是目的是呈现给用户简单是使用模式,同时也请大家区分出并行和并发的区别)。


我们先通过一张图来看看传统程序运行和Actor程序运行的不一样。

forum.php.png


那么为什么使用Actor呢?


在NF中,使用Actor的目的有2种:


1:服务器希望计算机的其他计算单元能帮它分摊计算资源,主要体现在大量计算密集行为产生的时候;
比如寻路导航,比如某时刻大量的预计算行为。


2:服务器希望主线程在处理计算密集行为的时候,部分IO瓶颈能够有其他非主线程能够代替它去等IO结束并降低使用要求;
比如mysql数据存储层(MysqlPlugin提供了同步和异步2种访问方式,其中异步访问即是使用actor技术实现),nosql数据存储层(NosqlPlugin提供了同步和异步2种访问方式,其中异步访问即是使用actor技术实现),http-client服务等。


作为一个actor管理模块的时候,在NF中,他是必须要运行在主线程,提供各种操作接口,最主要的几个接口分别有:
申请actor
释放某个actor
发消息给某个actor
actor收到消息的回调handler

他们在C++代码中是:

  1. class NFIActorModule : public NFIModule
  2. {
  3. public:
  4.     template<typename BaseTypeComponent, typename BaseType>
  5.     int RequireActor(BaseType* pBase, int (BaseType::*handler_end)(const NFGUID&, const int, const int, const std::string&))
  6.     {
  7.         if (!TIsDerived<BaseTypeComponent, NFIComponent>::Result)
  8.         {
  9.             //BaseTypeComponent must inherit from NFIComponent;
  10.             return 0;
  11.         }

  12.         int nActorID = RequireActor();
  13.         if (nActorID >= 0)
  14.         {
  15.             AddComponent<BaseTypeComponent>(nActorID);
  16.             AddEndFunc<BaseType>(nActorID, pBase, handler_end);

  17.             return nActorID;
  18.         }

  19.         return -1;
  20.     }

  21.     virtual bool SendMsgToActor(const int nActorIndex, const NFGUID& objectID, const int nEventID, const std::string& strArg) = 0;
  22.     virtual bool HandlerEx(const NFIActorMessage& message, const int from) = 0;
  23.     virtual bool ReleaseActor(const int nActorIndex) = 0;
  24. };
复制代码




下面我们来讲解一个Actor完成的使用流程,比如当我们因为http访问数据,需要使用一个Actor的时候。


1:我们在主线程申请使用一个Actor, RequireActor,此时同步传入主线程回调函数
2:传入需要执行的任务内容,SendMsgToActor
3:Actor任务执行完毕,NF把结果通过第一步注册的回调函数传出来,并在主线程调用回调函数;
4:根据结果做自己的业务操作,比如http登陆成功或者失败,消费金钱多少
5:根据ActorID释放Actor


下面是NF中实际使用过程中的代码:
  1. //Component类的所有代码都是在actor(非主线程运行)
  2. class NFCHttpComponent : public NFIComponent
  3. {
  4. public:
  5.     NFCHttpComponent(NFGUID self, const std::string& strName): NFIComponent(self, strName)
  6.     {
  7.     }

  8.     virtual ~NFCHttpComponent()
  9.     {

  10.     }

  11.     virtual int OnASyncEvent(const NFGUID& self, const int event, std::string& arg)
  12.     {
  13.         return 0;
  14.     }

  15. protected:
  16.     virtual NF_SHARE_PTR<NFIComponent> CreateNewInstance()
  17.         {
  18.                 return  NF_SHARE_PTR<NFIComponent> (NF_NEW  NFCHttpComponent(NFGUID(1, 2), ""));
  19.         }

  20. };


  21. //Module的所有代码都是在主线程运行的
  22. class NFCTestModule : public NFIModule
  23. {
  24.         virtual bool Init()
  25.         {
  26.                 m_pActorModule = pPluginManager->FindModule<NFIActorModule>();

  27.                 int nActorID = m_pActorModule->RequireActor< NFCHttpComponent>(this, &NFCTestModule::RequestAsyEnd);

  28.                 m_pActorModule->SendMsgToActor(nAcotrID, self, nEvetID, arg))

  29.                 return true;
  30.         }


  31.     int RequestAsyEnd(const NFGUID& self, const int nFormActor, const int nSubMsgID, const std::string& strData);
  32.    {
  33.        return 0;
  34.    }

  35. }
复制代码




NF项目为开源的分布式服务器解决方案,其中包含了网络库,actor库,以及数据驱动等新技术,能大幅提升开发效率节省开发周期以及提高程序的稳定性。
项目地址 https://github.com/ketoo/NoahGameFrame
如感觉对您有帮助,请给与star,同时也邀请广大同行参与开发和维护,作者QQ 342006,交流QQ群 341159815。
欢迎转载,转载请注明来源,本文版权归作者所有!



回复

使用道具 举报

0

主题

1

帖子

16

积分

Newbie

Rank: 1

积分
16
发表于 2016-12-30 11:53:19 | 显示全部楼层
沙发,666666
回复 支持 反对

使用道具 举报

2

主题

5

帖子

30

积分

Newbie

Rank: 1

积分
30
发表于 2016-12-31 22:02:43 | 显示全部楼层
回复

使用道具 举报

2

主题

5

帖子

30

积分

Newbie

Rank: 1

积分
30
发表于 2016-12-31 22:08:23 | 显示全部楼层
int RequestAsyEnd(const NFGUID& self, const int nFormActor, const int nEventID, const std::string& strData)


两个函数一样了啊
回复 支持 反对

使用道具 举报

30

主题

111

帖子

632

积分

Administrator

Rank: 9Rank: 9Rank: 9

积分
632
 楼主| 发表于 2017-1-1 03:43:26 | 显示全部楼层
......点 发表于 2016-12-31 22:08
int RequestAsyEnd(const NFGUID& self, const int nFormActor, const int nEventID, const std::string& s ...

copy多了,多谢指出
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | Register Now

本版积分规则

 

GMT+8, 2018-8-15 13:52 , Processed in 0.076711 second(s), 27 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表