2

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

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 实例数据发送到日志服务器,这会使日志服务器复杂化,有人有好的想法吗?

4

2 回答 2

2

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

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

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

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

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

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

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

于 2012-09-04T05:49:36.007 回答
0

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

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

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

于 2012-09-04T06:54:12.600 回答