记一次游戏运维全过程及部署方案 | 峰值RPM达到2W以上,QPS达到0.5k以上

项目技术栈

  • 游戏在微信中运行,使用cocos开发。
  • 后端部署在debian服务器,使用 goravel 开发。

需求

  • 本次预计5-10万用户,每个用户可玩多次游戏。
  • 活动发布后会进入大量用户,瞬时并发较大,初步评估高峰qps可达1000左右。
  • 游戏活动结束后 半月后下线。

部署方案

计算量分析

整个游戏过程只存储用户信息和用户游戏数据,无复杂计算,因为只需购买一个月,所以服务器购买了 8核16G

带宽分析

接口流量分析

接口流量平均每个 0.5kB,达到1000qps那么流量峰值为:0.5kB*1000 = 500kB/s = 0.5M/s。
接口流量

所以服务器理论带宽至少5M,实际上要购买10M以上的,留足可用带宽,因为高峰期可能更高翻几倍都是有可能的。
云服务器有一种按流量收费的类型,瞬时并发高的项目很适合使用这种类型的服务器
以下是不同带宽的价格差异

8核16G 5M带宽价格
5M带宽价格

8核16G 10M带宽价格
10M带宽价格

8核16G 50M带宽价格
50M带宽价格

8核16G 按量收费上限100M
按量收费上限100M

游戏加载流量分析

游戏加载流量分析
单次加载流量需要3M,那么如果千人同时访问那么游戏加载的流量高达:1000*3MB = 3000M/s,那么需要3WM带宽。
我们购买服务器时可以看到服务器的带宽最多是100M,达不到我们的要求,所以游戏资源文件肯定不能放在服务器上。

所以游戏资源我们放在对象存储上,开启对象存储的静态网站功能,绑定自己的域名。

对象存储流量价格
可以看到对象存储价格还是比较便宜,以下是带宽限制的描述

云存储带宽

实际运行数据分析

nginx 访问日志分析

access.log文件

nginx 文件大小 680MB

数据分析脚本

#!/usr/bin/env python3
import re
import argparse
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime, timedelta
from collections import defaultdict
import numpy as np
import pandas as pd
from matplotlib.ticker import MaxNLocator
import matplotlib.font_manager as fm
import os

import matplotlib

matplotlib.rc("font", family='YouYuan')


def parse_log_line(line):
    """解析单行 Nginx 日志"""
    pattern = r'^(?P<ip>\S+) \S+ \S+ \[(?P<time>[\w:/]+\s[+\-]\d{4})\]'
    match = re.match(pattern, line)
    if not match:
        return None, None

    ip = match.group('ip')
    time_str = match.group('time')

    try:
        dt = datetime.strptime(time_str, '%d/%b/%Y:%H:%M:%S %z')
        return ip, dt
    except ValueError:
        return None, None


def analyze_log(log_file, top_ips=10):
    """分析日志文件并生成图表"""

    # 初始化数据结构
    per_second = defaultdict(int)
    per_minute = defaultdict(int)
    ip_activity = defaultdict(int)
    timeline = []

    # 设置筛选日期阈值(9月29日)
    cutoff_date = datetime(2023, 9, 29, 0, 0, 0).replace(tzinfo=datetime.now().astimezone().tzinfo)

    # 解析日志文件
    with open(log_file, 'r') as f:
        for line in f:
            ip, dt = parse_log_line(line)
            if not dt:
                continue

            # 转换为本地时区
            dt = dt.astimezone()

            # 只统计9月29日之后的数据
            if dt < cutoff_date:
                continue

            # 时间点统计
            sec_key = dt.replace(microsecond=0)
            min_key = dt.replace(second=0, microsecond=0)

            per_second[sec_key] += 1
            per_minute[min_key] += 1
            ip_activity[ip] += 1
            timeline.append(dt)

    if not timeline:
        print("未找到有效的日志条目")
        return

    # 计算时间范围
    min_time = min(timeline)
    max_time = max(timeline)
    time_range = max_time - min_time

    # 创建单独的图表
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")

    # 1. 每分钟请求数图表(单独保存)
    plt.figure(figsize=(15, 6))
    plt.suptitle('标题', fontsize=20, fontweight='bold', y=0.99)
    minutes = sorted(per_minute.keys())
    requests_per_minute = [per_minute[m] for m in minutes]

    plt.plot(minutes, requests_per_minute, 'b-', linewidth=1.5)
    title_rpm = '每分钟请求数 (RPM)'
    plt.title(title_rpm)
    plt.xlabel('时间')
    plt.ylabel('请求数')
    plt.grid(True, linestyle='--', alpha=0.7)

    # 设置X轴格式
    if time_range > timedelta(days=1):
        plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m/%d %H:%M'))
    else:
        plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))

    plt.gcf().autofmt_xdate()
    plt.setp(plt.gca().get_xticklabels(), visible=True, rotation=30, ha='right')
    plt.tight_layout()

    rpm_file = f"logs/rpm_chart_{timestamp}.png"
    plt.savefig(rpm_file)
    print(f"RPM图表已保存至: {rpm_file}")
    plt.close()

    # 2. 每秒请求数图表(峰值区域)(单独保存)
    plt.figure(figsize=(15, 6))

    # 找到峰值时间段(前5%的时间段)
    peak_period = sorted(per_second.items(), key=lambda x: x[1], reverse=True)
    peak_period = peak_period[:max(10, len(peak_period) // 20)]
    peak_times = [t for t, _ in peak_period]

    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小武的开发空间

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值