django 频道在组用户之间共享实例变量

Posted

技术标签:

【中文标题】django 频道在组用户之间共享实例变量【英文标题】:django channels share instance variable between group users 【发布时间】:2020-05-20 15:34:03 【问题描述】:

我正在 django 上开发一个在线游戏,我正在使用频道进行实时连接,但不幸的是,对于每个用户,我都有一个单独的游戏实例。

我想要的是,对于第一个用户,我使用 StartGame 的对象开始游戏,并希望对其他用户也使用相同的实例对象,因为我想分享游戏的当前状态。

我怎样才能只与该组的其他成员共享游戏实例?

我的一个想法是将游戏的当前状态保存在一个文件中,并将文件的路径保存在 db 中,让另一个用户检索保存的游戏状态并玩他/她的机会并再次保存,但这是否有效以及正确的做法?

网络游戏的实际场景是什么?

更新

我已经实现了,但它是正确的方式还是安全的?

我创建了一个全局变量GAME_POOL = 并为第一个用户存储了带有键channel_group_name 的游戏实例,然后为其他用户检查GAME_POOL 是否具有channel_group_name 的现有值,然后设置self.game = GAME_POOL['channel_group_name'] 及其工作。

但这又是实现这一目标的安全且好方法?

游戏结束后我将删除它。

【问题讨论】:

将游戏状态直接存储在数据库中怎么样?为什么要先存储在文件中? 这对我来说很难,因为游戏有太多的模型,每一步都保存在数据库上,而且对于很多用户来说,数据库上的负载是无用的......我看到的最佳选择是共享实例群用户之间的游戏……如果能实现那就更好了。 @Ken4scholars 请检查更新 如果你想将状态存储在内存而不是数据库上,如果组数太大而导致内存膨胀怎么办?您是否需要持久性,因为游戏工作者可能会遇到问题并关闭?所有这些都取决于您的用例,这是您必须自己回答的问题。没有唯一正确的方法。 @Ken4scholars 你是对的,但是程序已经在 ram 中占用了 20 mb,当我保存对象实例时,它的大小为 5kb,所以我认为我可以在 ram 中而不是在 db 上加载这个实例只是因为它只有 5kb 并且已经花费了 20mb 进行处理。请告诉我这是实现这一目标的正确方法吗?? 【参考方案1】:

如果您真的想将游戏状态存储在 RAM 中(尽管 Ken4scholars 在 cmets 中提到了限制),您还可以将共享变量移动到 middleware 中,如下所示:

from channels.middleware import BaseMiddleware


class GameStateMiddleware(BaseMiddleware):
    def __init__(self, inner):
        self.inner = inner
        self.game_states = 

    async def __call__(self, scope, receive, send):
        query = dict((qp.split('=') for qp in scope['query_string'].decode().split("&")))
        game_id = query.get('game_id')

        if game_id not in self.game_states:
            game_states[game_id] = 

        scope['game_state'] = self.game_states[game_id]
        return await super().__call__(scope, receive, send)

在消费者内部,共享变量将在self.scope['game_state'] 中可用。由于它是通过引用传递的,因此您也可以对其进行写入,但是,您需要注意同步(例如通过将锁也注入作用域)。

【讨论】:

以上是关于django 频道在组用户之间共享实例变量的主要内容,如果未能解决你的问题,请参考以下文章

C ++在更多对象实例之间共享一个变量

在所有 vue 组件实例之间共享变量

jQuery - 跨实例共享变量

使用 sockjs 支持多个私人频道

哪些变量是共享的,而不是在 python 中的进程之间共享?

static关键字