【完整APP】SpriteKit引擎开发iOS小游戏之四(服务端搭建)

【服务端总体设计】

由于游戏APP中使用了账号与排行榜功能,所以需要部署服务器来完成数据管理以及处理网络请求。

  • 服务器介绍
    服务器选择的是阿里云服务器。弹性计算服务(Elastic Compute Service, 简称ECS)是一种简洁高效、运算效率可以弹性地伸缩,具有更多的性能与功能,更好的数据保护和可靠性。服务器需要24小时不间断运行,如果使用云服务器就会节省开支。
  • 数据库介绍
    腾讯云数据库MySQL(TencentDB for MySQL)为用户提供安全可靠,易于维护的数据存储服务。使用它可以达到分钟单位的数据库部署和弹性扩展,既安全,又可靠运行,方便维护。云数据库MySQL带有恢复与备份、监控、快速扩容、数据传输等辅助工具,减轻数据库维护工作量,专注于业务发展。
  • 环境与框架
    服务端代码使用利用Flask框架,用Python编写的脚本代码,集成了数据库封装与业务逻辑执行,完成请求响应。Flask为Python语言实现的轻量级Web框架,代码简洁且易扩展。如图4-2所示,Flask的工作模式是在程序中把一个视图函数连接到一个URL,每次有请求访问该URL,系统就会执行那个提前为URL分配好的方法并得到函数的返回值。
    在这里插入图片描述

【服务器代码实现】

  1. 数据库部分代码:这部分针对数据库的初始化、功能使用进行了封装。关于每次函数操作都通过conn.ping(reconnect=True)保证连接。并及时的conn.commit()。
import json
import pymysql
from flask import  Flask, request, jsonify


#连接数据库
config = {
    "host": "这里是数据库的主机地址保密哦",
    "port": 10058,
    "user": "这里是数据库用户名保密哦",
    "password": "这里是数据库密码保密哦",
    "db": "game",
    "charset": "utf8"
}
conn = pymysql.connect(**config)
cur = conn.cursor()

#数据库登陆检验
def LoginCheck(username, password):
    conn.ping(reconnect=True)
    sql_search_password = "select password from playersInfo where username=%s"
    cur.execute(sql_search_password, (username))
    user_password = cur.fetchone()
    if user_password is None:
        conn.commit()
        return False
    search_user_password = user_password[0]
    if search_user_password == password:
        conn.commit()
        return True
    else:
        conn.commit()
        return False

#数据库注册检验
def RegisterNewPlayer(username, password):
    conn.ping(reconnect=True)
    sql_search_user = "select * from playersInfo where username=%s"
    search_user_result = cur.execute(sql_search_user,(username))
    if search_user_result is 1:
        conn.commit()
        return False
    else:
        sql_insert_user = "insert into playersInfo values(%s,%s)"
        cur.execute(sql_insert_user, (username, password))
        conn.commit()
        return True

#数据库查询排行榜
def GetRankInfo(username, islogin):
    conn.ping(reconnect=True)
    rank_info = {
        "self_score": "",
        "self_rank": "",
        "p1_name": "",
        "p1_score": "",
        "p2_name": "",
        "p2_score": "",
        "p3_name": "",
        "p3_score": "",
        "p4_name": "",
        "p4_score": "",
        "p5_name": "",
        "p5_score": "",
        "p6_name": "",
        "p6_score": ""
    }
    if islogin == 'yes':
        sql_search_self = "select * from scoreRank where username=%s"
        cur.execute(sql_search_self, (username))
        self_information = cur.fetchone()
        if self_information is None:
            rank_info["self_score"] = '暂无数据'
            rank_info["self_rank"] = '暂无数据'
        else:
            rank_info["self_score"] = self_information[1]
            sql_search_self_rank = "select u.rank from (select username, ( @ranknum := @ranknum+1) as rank from scoreRank,(select( @ranknum := 0) ) b order by score desc)u where u.username =%s;"
            cur.execute(sql_search_self_rank, (username))
            rank_info["self_rank"] = cur.fetchone()[0]

    cur.execute("select * from scoreRank order by score desc")
    rank_index = 0
    for i in range(6):
        rank_index += 1
        res = cur.fetchone()
        if res is not None:
            if rank_index == 1:
                rank_info["p1_name"] = res[0]
                rank_info["p1_score"] = res[1]
            elif rank_index == 2:
                rank_info["p2_name"] = res[0]
                rank_info["p2_score"] = res[1]
            elif rank_index == 3:
                rank_info["p3_name"] = res[0]
                rank_info["p3_score"] = res[1]
            elif rank_index == 4:
                rank_info["p4_name"] = res[0]
                rank_info["p4_score"] = res[1]
            elif rank_index == 5:
                rank_info["p5_name"] = res[0]
                rank_info["p5_score"] = res[1]
            else:
                rank_info["p6_name"] = res[0]
                rank_info["p6_score"] = res[1]
        else:
            if rank_index == 1:
                rank_info["p1_name"] = "暂无数据"
                rank_info["p1_score"] = "暂无数据"
            elif rank_index == 2:
                rank_info["p2_name"] = "暂无数据"
                rank_info["p2_score"] = "暂无数据"
            elif rank_index == 3:
                rank_info["p3_name"] = "暂无数据"
                rank_info["p3_score"] = "暂无数据"
            elif rank_index == 4:
                rank_info["p4_name"] = "暂无数据"
                rank_info["p4_score"] = "暂无数据"
            elif rank_index == 5:
                rank_info["p5_name"] = "暂无数据"
                rank_info["p5_score"] = "暂无数据"
            else:
                rank_info["p6_name"] = "暂无数据"
                rank_info["p6_score"] = "暂无数据"
    print(rank_info)
    conn.commit()
    return rank_info

#数据库上传成绩
def UploadScore(username, score):
    conn.ping(reconnect=True)
    sql_search_user_record = "select * from scoreRank where username=%s"
    search_record_result = cur.execute(sql_search_user_record,(username))
    if search_record_result is 1:
        #存在记录则更新
        player_score = cur.fetchone()[1]
        if int(score) > player_score:
            sql_update_score = "update scoreRank set score=%s where username=%s"
            cur.execute(sql_update_score, (score, username))
            conn.commit()
            return 1
        return 2

    else:
        #插入新记录
        sql_insert_score = "insert into scoreRank values(%s,%s)"
        cur.execute(sql_insert_score, (username, score))
        conn.commit()
        return 3
  1. 使用Flask框架处理网络请求,分配URL参数
app = Flask(__name__)

#处理登陆请求
@app.route('/login', methods = ['GET', 'POST'])
def login():
    print('accept login request')
    username = request.args.get('username')
    password = request.args.get('password')
    is_right_password = LoginCheck(username, password)
    if is_right_password is True:
        response_info = "enable"
    else:
        response_info = "no"
    return response_info

#处理注册请求
@app.route('/register', methods=['GET', 'POST'])
def register():
    print('accept register request')
    username = request.args.get('username')
    password = request.args.get('password')
    whether_register = RegisterNewPlayer(username, password)
    if whether_register is True:
        response_info = "enable"
    else:
        response_info = "no"
    return response_info

#处理排行榜请求
@app.route('/rankInfo', methods=['GET', 'POST'])
def rankInfo():
    print('accept query rank request')
    username = request.args.get('username')
    login_status = request.args.get('islogin')
    rank_data = GetRankInfo(username, login_status)
    responseData_json = json.dumps(rank_data)
    return responseData_json

#处理上传请求
@app.route('/upLoadScore', methods = ['GET', 'POST'])
def upLoadScore():
    print('accept upload request')
    username = request.args.get('username')
    score = request.args.get('score')
    result = UploadScore(username, score)
    if result == 1:
        responseInfo = "刷新记录成功"
        return responseInfo
    elif result == 2:
        responseInfo = "未打破记录"
        return responseInfo
    responseInfo = "上传记录成功"
    return responseInfo


if __name__ == '__main__':
    app.run(debug=True, threaded=True, port=80, host='0.0.0.0')


收到对应URL请求的时候,就会自动开一个线程去执行下边的映射函数内容。return的信息就是作为对请求的响应。

  1. 挂载于服务端:
    使用 nohup 命令将脚本挂载于服务端后台运行,并将作业输出定向到nohup.out文件中

【性能监控与分析】

在ECS实例利用云监控的Dashboard功能,给云数据库设置全局监控总揽,可随时查看监控状态如图6-5。ECS实例基础监控包括CPU使用率(%)、网络流入带宽(bit/s)、网络流出带宽(bit/s)、磁盘平均BPS(bps)、磁盘平均IOPS(次/秒)。根据实际的业务情况可以在平台中设置各项监控指标的报警阀值,也可以额外的添加负载均衡监控、RDS监控、进程监控。
在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章