用nginx+uwsgi+redis实现游戏GM聊天功能

本文介绍了如何通过nginx、uwsgi和redis实现游戏GM聊天功能。在原始需求中,GM需要能与所有游戏服内的玩家进行聊天。需求分析后,决定通过web服务器存储GM数据,游戏服定时获取。具体实现中,利用nginx作为web服务器,uwsgi作为代理,redis存储数据,实现数据在各服务器间的传递。游戏客户端与游戏服务器保持TCP长连接,其他部分使用HTTP短连接。代码部分因隐私原因未展示。
摘要由CSDN通过智能技术生成

原始需求

一个客服GM能够加所有游戏服内的玩家为好友,并能进行聊天。具体功能如下:
* GM上、下线
* 加游戏玩家为好友
* 删游戏玩家为好友
* GM发送聊天消息
* 玩家推送聊天消息
额外限定:一个GM账号能够添加多个游戏玩家为好友,而一个游戏玩家只能被一个GM账号添加

需求分析

因为我们游戏内并没有跨服聊天、跨服好友这种功能,而且以后也不会支持,所以让GM在游戏里面创建角色,然后加各个游戏服的玩家进行聊天的方案是无法实施的。 而且GM实际上并不是一个游戏角色,也不用在游戏内创建。
整个的难点是,如何让各个游戏服访问到GM发过来的各种数据,如何将玩家的数据推送给GM。

具体实现

为了实现GM的数据在各个服务器传递,我们采用了一种简单的方案:将GM的数据放在我们的web服务器上,各个游戏服定时从web服务器去拿数据。
这种方案很简单,web服务器与游戏服不用长连接,直接用http的get和post方法就可以拿数据了。整个架构如下:


GM1-------运维聊天服--------游戏web服务器------游戏服务器1--------游戏客户端1
            |                |                |
            |                |                |
            GM2             游戏服务器2       游戏客户端2

这里客服GM1和GM2都用的web界面与游戏客户端聊天。
运维聊天服存在是因为:
* GM的创建需要运维那边的审批。。
* 游戏的web服务器可以进行白名单审查,只有运维聊天服的ip可以访问游戏的web服务器
上图中只有游戏客户端与游戏服务器是采用的tcp长连接,其他都是使用http短连接来实现。
web服务器采用的是nginx,而不是nodejs。nginx方案挺成熟的,而且部署也很容易。
由于,我对python的熟悉程度比lua程度高很多,所以用了uwsgi来做代理,而不是直接用lua来写。
而数据库则采用的redis,redis设置了定时存盘了。数据格式设置可参考我之前提的文章,基本都是
gm:%d:name这种格式,key表示gmx的名字是什么,val表示名字。

实现代码

nginx和uwsgi的配置已略去。因为隐私原因,相关IP已略去,代码里面也有足够的注释,不再赘述:

#encoding: utf-8

"""
新功能:
* GM注册
* GM上线
* GM下线
* 加游戏玩家为好友
* 删除游戏好友
* GM推聊天信息
* 玩家推聊天信息

---
消息数据格式为utf-8处理后的base64编码:游戏服和GM发过来的都是base64格式,要注意分隔符没做base64处理
GS只能用get方式推送消息,所以参数用类似于urllib quote(urlencode)进行了封装。运维客户端也用get

一个GM账号能添加多个游戏玩家为好友,而一个游戏玩家只能被一个GM账号添加

"""

from config import *
from json import dumps, loads
import base64
import urllib
import urllib2
import copy
import redis


MSG_SEPARATOR = "," #分割信息
MAX_RECV_AMOUNT = 10 #每次消息10条吧
MSG_MAX_LEN = 500 #消息不弄太长了

CONTENT_TYPE = [("Content-Type","text/html")]
HTTP_STATUS = {
    200: "200 OK",
    404: "404 Not Found",
}

GAME_SERVER_INFO_URL = "http://xxxxxyyyyy"

ROLE_INFO_URL = "http://xxyyy?uid=%s&hostnum=%s"


red = redis.StrictRedis(host=REDIS.HOST, port=REDIS.PORT, db=REDIS.DB)

#游戏服务器IP白名单
if not globals().has_key("gServerIP"):
    gServerIP = {}
    res_data = urllib2.urlopen(GAME_SERVER_INFO_URL)
    res = res_data.read()
    res_list = res.split("\n")
    for val in res_list: 
        if not val:
            continue
        _, port, ip, _  = val.split(" ") 
        gServerIP[ip] = port

gGMIP = {
        "xxxxyyyy" : 1,
}

def is_gm_account_exist(account_id):
    if red.get("gm_account:%s:name" % account_id):
        return 1
    return 0

def is_inter_server(hostnum):
    if ( int(hostnum) >= 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值