【问题标题】:Design log server for MMO game为 MMO 游戏设计日志服务器
【发布时间】:2012-09-04 14:54:12
【问题描述】:

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

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 语言。如果处理得当,其余代码甚至都不应该关心——更不用说知道——记录器背后的实现了。日志记录会对性能产生巨大影响,并且由于您承认缺乏经验,因此您必须向团队的其他成员寻求帮助,并确保使用准备好的语句来避免 SQL 注入(在C++,如果你不知道这是什么意思)。
  • 感谢您的重播。日志服务器控制日志的数据库,它将执行 sql 命令。问题是在游戏服务器上生成 sql 然后将 sql 字符串发送到日志服务器或将日志数据发送到日志服务器并使用数据服务器生成 sql 之间的选择?对于sql注入部分,由于log模块与播放器没有直接交互,所以不用担心。
  • 问题是在游戏服务器上生成sql然后将sql字符串发送到日志服务器或将日志数据发送到日志服务器并使用数据[服务器]生成sql-这个词应该删除,不知道怎么编辑,所以重播一遍。

标签: c++ logging mmo


【解决方案1】:

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

Log Server 应该是一个单独的组件,它以对您来说最方便的任何格式(性能、详细程度、大小等)进行日志记录,并且只要 API 足够灵活,就可以将其编写为底层实现可以在游戏服务器不知情的情况下更换。

通过将底层实现的完整知识与游戏服务器代码相结合,您不仅可以防止这种未来的工作,而且您还可能将大量工作投入到游戏服务器的代码中,这些工作可以由一个单独的线程完成日志服务器。更不用说,通过向 SQL 开放 API,您将潜在的错误置于游戏服务器代码中,否则这些代码将被集中化。

在设计面向对象系统时,前瞻性、替换驱动的方法是理想的选择。如果您可以避免耦合到除 API 之外的任何内容,那么您始终可以替换 API 下的任何内容而不影响外部代码(忽略错误),但这需要考虑将其放入 API 以确保它具有足够的灵活性以供未来使用.

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

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

这就是说,将日志相关的 SQL 放到 Log Server 中,而不是 Game Server 中。游戏服务器不应该关心日志服务器除了一般的“日志记录”之外还做什么。

【讨论】:

  • 太好了,答案就是我想要的!再次感谢!
【解决方案2】:

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

因此,游戏服务器和日志服务器之间的 API 应该只包含您要记录的变量,而不是执行此操作的代码。

这完全避免了 SQL 注入这一事实是一个附带好处。但这仍然是一个真正的好处。如果您要记录用户名,则必须已经考虑 SQL 注入。

【讨论】:

  • 感谢您的回答。我们的项目在输入中使用 mysqlpp 和同事过滤字符(例如用户名),例如 '%'、'=' 等。我不知道怎么做 sql prepaired statements,你能给我一些提示吗?
  • 显然,对于 mysqlpp 他们被称为template queries
猜你喜欢
  • 1970-01-01
  • 2015-01-01
  • 1970-01-01
  • 2011-07-05
  • 2011-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多