为MMO游戏设计日志服务器

Design log server for MMO game

本文关键字:日志 服务器 MMO 游戏      更新时间:2023-10-16

我是游戏服务器设计的新手,现在被分配到重构日志服务器的任务中。我创建了一个类日志,用于游戏服务器和日志服务器之间的通信。

class Log
{
    public:
        void    encode(Encoder& encoder) const;
        int     decode(Decoder& decoder);
    private:
        std::string sql_cmd;
}

在游戏服务器上,有一个类用于向日志服务器发送日志请求。

class LogHelper
{
public:
        static void LogItemChange(const GameShare::GameItem& item, const PackageChangeDetails& pcd);
        {
                Log log(get_item_change_sql(item,pcd);
                send_to_log_server();
        }

private:
        static std::string get_item_change_sql(const GameShare::GameItem& item, const PackageChangeDetails& pcd);
}

问题是:

  1. 我应该在游戏服务器上生成sql文本吗?如果在游戏服务器上生成sql文本,是否会对游戏服务器的性能产生不良影响?

  2. 如果没有在游戏服务器上生成sql文本,那么应该在日志服务器上生成sql文本。我应该把GameItem和PackageChangeDetails实例数据发送到日志服务器,这会使日志服务器复杂化,有人有好的帮助吗?

如果日志的SQL是由Game Server生成的,那么几乎不需要任何日志服务器代码,因为它成为数据库管理器部分的直通,Game Server几乎肯定已经知道了(尽管我认为它们可能是不同的数据库),或者可以很容易地与之交互。

日志服务器应该是一个单独的组件,可以以任何对您最方便的格式(性能、冗长程度、大小等)进行日志记录,只要API足够灵活,它就可以在Game Server不知道的情况下被替换。

通过将底层实现的完整知识与Game Server代码相结合,您不仅可以防止未来发生这种情况,而且还可以在Game Server的代码中投入大量工作,这些工作可以由日志服务器上的单独线程完成。更不用说,通过向SQL开放API,您将潜在的bug放在了Game Server代码中,否则这些代码将是集中的。

前瞻性、替换驱动的方法是设计面向对象系统的理想方法。如果你可以避免耦合到除了API之外的任何东西,那么你总是可以替换API下面的任何东西而不影响外部代码(忽略bug),但这需要考虑API,以确保它在未来有足够的灵活性。

在这一点上,我强烈建议您将Logging API实现为一个纯虚拟接口,然后在其上编写一个与数据库对话的实现,可能使用一个单独的实现来日志记录到文本文件(为了方便,在没有数据库可访问的情况下进行本地测试,如果这是一个问题的话)以及一个do-nothing实现。考虑到前两个,它应该有助于引导您进行更好的设计,并远离耦合。

这也可能导致其他类实现的一些基本接口(例如,public: std::string to_log_string() const;),然后Logger可以使用这些接口引入任何实现对象,并将其快速转换为日志消息。

所有这些都意味着,将日志相关的SQL放入日志服务器,而不是游戏服务器。游戏服务器不应该关心日志服务器除了一般的"日志记录"之外做什么。

不要在游戏服务器上生成SQL文本。也不要在日志服务器上执行此操作。事后看来,SQL应该只有准备了语句。在运行时生成查询和在运行时产生索引一样疯狂。因此,将最终SQL文本的生成留给数据库。

因此,游戏服务器和日志服务器之间的API应该只包含您想要记录的变量,而不是这样做的代码

这完全避免了SQL注入,这是一个附带的好处。但这仍然是一个真正的好处。如果您的日志与用户名一样多,那么您必须已经考虑SQL注入。