现在的位置: 首页 > 综合 > 正文

一日一点RakNet(33)–Cloud Computing

2014年11月18日 ⁄ 综合 ⁄ 共 3424字 ⁄ 字号 评论关闭

云计算概览

 

通过服务器云实现客户端可访问的内存/事件

       有时想要大量的没有相互连接的客户端,它们不需要相互知道对方的存在而共享内存或得到事件的通知。例如:

       1. 高性能服务器浏览器

       2. 游戏内百万用户的统计

       3. 云计算

       在云服务中的“云”意味着系统支持分布式服务器。任何的服务器可以Post()到服务器,或从服务器上Get()信息。不论客户端从什么服务器上订阅的服务,Post()操作可以定制给其他客户端或被其他的客户端Get()。服务器可以在运行时增加或移除,系统的运行也不会受到影响,继续按照期望的情况运行。这要求系统可以根据玩家的负载进行扩展,可以使用自己的服务器或者虚拟的服务器,例如Rackspace

       系统的设计假设所有的服务器完整连接。在使用CloudServer::AddServer()方法将服务器加入进来之前,应该验证这些服务器。TwoWayAuthenticationConnectionGraph2插件可以帮助实现这个功能。可以通过运行/修改CloudServer例子来实现,这个例子已经实现这个功能。

       通过静态IP地址,没有路由或有端口打开,可以通过Internet访问服务器。

       注:系统的设计是当客户端连接到服务器时,客户端数据才会持续到达。服务器本身可以执行本地操作或使用本地的客户端进行持久化。

 

代码使用方法:

       在服务器上,可以有选择地限制下载或上传,以减少内存或带宽使用。

      
CloudServer cloudServer;
       rakPeer->AttachPlugin(&cloudServer);
       //

限制客户端可以向服务器上传多少字节数据

      
cloudServer.SetMaxUploadBytesPerClient(MAX_UPLOAD_BYTES); 
       cloudServer.SetMaxBytesPerDownload(MAX_DOWNLOAD_BYTES);

 

在客户端:

      
CloudClient cloudClient;

      
rakPeer->AttachPlugin(&cloudClient);

      
//
可选:提供一个分配器存储或释放下载行

      
Cloud_Allocator cloudAllocator;

      
//
可选:你会想要真正提供一个实例处理下载。

      
Cloud_ClientCallback clientCallback;

      
//
设置分配内存的回调函数

      
cloudClient.SetCallbacks(&cloudAllocator, &clientCallback);

      
//
每一个上传关联一对密钥

      
Cloud_DataKey dataKey;

      
dataKey.primaryKey="ApplicationName";
       dataKey.secondaryKey=ID_PLAYER_COUNT; // Enumeration
       unsigned char playerCount=16;
       //

将数据上传到云,我们已经连接的服务器

      
cloudClient.Post(&dataKey, &playerCount, sizeof(playercount), serverAddressOrGuid);
       //

下载我们刚刚上传的数据,clientCallback会在查询完成时调用OnDownload成员

      
Cloud_KeyQuery query;
       query.keys.Push(dataKey, __FILE__, __LINE__);
       cloudClient.Get(&query, serverAddressOrGuid);

      
 

使用的情况:

 

服务器目录:

       为应用程序赋值一个秘密的唯一名字,将它作为Cloud_DataKey
私有密钥。使得每一个游戏服务器维护一个共同的枚举类型的列表,这些枚举类型代表了查询的域,例如PLAYER_COUNT PLAYER_LIST,和PLAYER_NAME。其他服务器的IP地址和RAkNetGUID属性是自动维护地。当一个游戏服务器的可以进行列表,使用CloudClient::Post()操作。查询其他的服务器,使用CloudClient::Get()操作,将你关心的CloudMemory_DataKey密钥传到Cloud_KeyQuery。如果在前面的调用中没有查询所有的密钥,可以使用CloudClient::Get()操作使用大量的密钥列表获得更多的细节信息;或使用重载的CloudClient::Get(),带有specificSystem参数,来获取更多详细信息。如果愿意,可以在CloudClient::Get()调用中定制updates,但通常这个操作不是必须的。游戏服务器如果从CloudServer(比如说crashing)断开了连接,那么它将被从云服务器列表清除。游戏服务器也可以手动调用CloudClient::Release()调用从列表中清除。

In-game
统计

       假设你想要从所有运行的服务器上追踪kills的数量(没有理解什么意思),游戏拥有百万个玩家,那么让每一个客户端单独访问一个数据库服务器根本不可行。同时呢,游戏运营商希望将数据库服务器进行隐藏。Cloud系统可以帮忙,在内存中镜像复制常用的统计信息。为了实现这个功能,每一个客户端需要将KillsPost()到服务器。每一个在云上的服务器有一个本地的客户端用于更新数据库。本地的客户端使用Get()方法查询或签署客户端的kill上传。本地客户端也会周期写到数据库服务器(或如果想要实时统计,它可以在每一次kill消息时写到数据库)。相似地,本地的客户端会从中心数据库读取更新的kill数量,将这个数据Post()到云上。最后,游戏客户端使用带有specificSystem参数的Get()函数来获取更新的kill数。

 

云计算:

       有时你想要通过许多客户端分隔一个问题。例如,在游戏等级中渲染灯光。云服务器可以协助充当发布事件协调者。每一个想处理这部分内容的客户端调用CloudClient::Post(),不用携带任何数据,仅仅通知准备好了执行这些处理。CloudMemory_DataKey::primaryKey或许是“LevelRender”,但是CloudMemory_DataKey::secondaryKey或许是ID_SIGNAL_READY。客户端也将调用Get()订制新的任务,例如ID_TASK_SUBSCRIPTION。要Post()结果,例如ID_TASK_COMPLETION。服务器会有一个本地客户端在127.0.0.1,包含了真正要解决的问题。这个本地的客户端会订阅ID_SIGNAL_READY。当通知到来时,问题被分开,用ID_SUBSCRIPTION调用Post()方法。数据域可以指定GUID,客户端应该处理这项任务。如果服务器上的本地客户端得到了Cloud_ClientCallback::OnDeletion调用,然后其中一个处理客户端丢失连接或崩溃了,处理的数据可以重新分配给其他的客户端。

      

分布式CloudServer实现

       基于迁移的带有DNSCloudServer的分布式认证实现参考Samples/CloudServer。参考Samples/CloudServer/readme.txt,其中包含了CloudServer的实现细节,如果在多个客户端之间实现负载平衡,以及支持插件的列表。

 

服务器目录实现

       使用CloudServer实例作为备份的高性能服务器目录的实现参考Samples/CloudClient。分布式拓扑使得新的服务器可以在不进行重启,配置或修改代码的前提下加入到服务器群。

       参考 CloudServer.hCloudClient.h文件,查看所有的函数和参数的一个完整列表。

 

By
北洋小郭

转载请注明出处,请勿用于商业用途,谢谢!

 

 

抱歉!评论已关闭.