FPS游戏漫谈优化包体传输

news2025/1/12 11:56:51

在游戏服务器的部署环境中,机房的网络带宽都是有限制的。如果通信传输的数据总量太大,会挤占带宽甚至达到带宽上限,影响正常消息发送。另外,如果包体太大,在弱网环境下的通信质量会变差,更容易发生丢包重传和延迟,而且大包对于截包和查找问题也不方便。因此我们需要对消息通信做优化,减少包体的大小和数量,进而减小传输的数据总量。

缩减包体大小
我们很容易理解包体太大对网络通信造成的负面影响。因为一个完整的数据包在通信协议底层也是拆成多个小包发送,在弱网环境下,每个小包都有可能发生丢包重传和延迟,叠加起来会让整个完整数据包也更容易出现问题。另外有实际经历的人会很理解从一大堆冗余数据里查找目标字段时的痛苦。

缩减包体大小的第一个方法是只传必要字段。

首先是使用前端静态表。策划配置的数据一般称为静态表,与存储玩家数据的动态表不同,静态表是只读不可修改的。建议对静态表的数据归类,数值类的放在服务端,显示类的放在客户端,这样好处是很多数据前端可以直接从前端静态表读取,不再依赖后端传输,后端通常只需要传一个id作为索引。

对于前后端静态数据如何划分是一个值得权衡的问题。通常来说,衡量的标准有两个维度:与前后端业务的相关性,以及该数据占用空间的大小。例如,数值类的数据与服务端计算强相关,因此适合放在服务端;而描述性的文字占用字节多,不宜通过服务端传输,因此放在客户端;图片和动画资源路径类的数据与客户端业务强相关,也放在客户端。

不过有时候前后端静态数据的划分界限并不那么清晰,这时候还需要结合其他要素做判断。例如,一个数值类的数据前后端都用到了,那么是否还需要放在回包消息中由后端传输呢?我们可以提前预判这个数据在将来变化的可能性大小,如果不太可能变化,那么就让前端直接从前端静态表中读取;反之,如果变化可能性很大,那么还是让前端从后端回包中获取该数据。这样做的好处是,模块上线后一旦需要数值调整,可以只需要后端对静态表做一次热更新,而前端不需要发额外的热更新,前者比后者对玩家的影响更小。

我们可以将前端静态表设计为后端静态表数据的超集,这样在选择本地读取还是后端传输时有更大的灵活性。

其次是优化消息结构体,减少冗余字段。例如下面的json数据用于描述玩家的功能列表中有哪些已开启:

“functionList”: [
{
“functionId”: 1
“isOpen”: true
},
{
“fuctionId”: 2
“isOpen”: false
},

]
1
2
3
4
5
6
7
8
9
10
11
可以将已开启功能的id直接放到一个列表中,精简为如下结构:

“openFunctionList”: [
1, 3, 4, …
]
1
2
3
任何一个合格的游戏服务器程序员都应该追求简单有效的协议模型。

缩减包体大小的第二个方法是对传输数据做压缩。

一般建议对传输数据开启压缩。常用的压缩算法有Gzip、LZ4、Deflate等。就拿最常见的Gzip来说,通常情况下它可以将json数据压缩到原来的1/3到1/2大小,用时仅为毫秒级别。不过压缩率也受到数据大小和数据内容的影响。如果原始数据中的内容重复率很高,数据量较大,那么压缩效果会更好,因为Gzip底层是基于LZ77算法和霍夫曼编码,对重复率高的内容做编码上的优化。

注意,某些二进制通信协议(如Msgpack)本身已对数据做了压缩,那么不要重复做压缩了,重复压缩并不能继续减小包体大小,反而会带来额外的性能开销。

减少推送消息的数量
这是从另一个维度减小传输数据总量。

首先是只推送给必要的对象。推送范围的判断有时候很容易,因为有时范围是固定的,例如一个游戏中的聊天室,每个玩家加入聊天室就默认进入了一个推送消息组,所有的聊天消息都会实时推送到这个消息组里的每个人。通常我们不提倡设立一个超大的聊天室,因为聊天消息的数量与参与人数是O(n^2)的关系,当人数增加时,聊天消息数量会迅速增加直至爆炸。

推送范围有时候又是灵活多变的,典型的例如一个MMORPG中的超大地图上的消息推送,这时就要用到通常所说的AOI算法,只推送给当前对象周围一定范围内的玩家。常用的AOI算法就是基于九宫格模型,还有的游戏会根据业务特点做模型优化,例如我曾经分享过重返帝国使用的梯形模型。
在这里插入图片描述

其次是降低推送的频率。例如,在重返帝国的游戏中,大地图上军队的血量并不需要在每次变化时都推送,可以每隔一小段时间做一次推送,这么细节的内容即使减少推送频率,也不会对玩家体验有明显的变化。降低推送频率的做法也叫推送裁剪。

对包体大小的权衡
要注意的是,包体并非越小越好,必要时还需要合并小包。在笔者的上一篇文章中,我们讲过大量小包的出现会降低网络带宽的利用率,同时导致弱网环境下的传输质量变差。针对这种情况,我们在不影响客户端表现的前提下,在业务层做多个小包的合并。例如,一个由服务端驱动的战斗一帧内向客户端推送了如下三条战报:

A|move|timestamp
B|att|C|timestamp
C|die|timestamp
1
2
3
原本是每产生一条新战报都推送,我们可以优化成服务器运行一帧后再合并推送:

A|move;B|att|C;C|die;timestamp
1
由于客户端也是逐帧渲染,原本一帧以内不同时刻到达客户端的小包实际也是在帧末统一处理和渲染,所以这样的改动不会对玩家体验有任何影响,但是网络传输的效率得到显著提升。

有时候我们也需要分拆大包。例如,在玩家登录游戏时,通常需要向客户端传递大量数据,有人会选择把这些数据全部放在一个接口中,例如:

登录大接口:
玩家基本信息(名字、等级、经验)
聊天历史消息
主城信息
好友信息
1
2
3
4
5
但是我们有充分理由不这么做,而是按功能拆分成多个接口,登录时依次调用它们:

接口一:玩家基本信息(名字、等级、经验)
接口二:聊天历史消息
接口三:主城信息
接口四:好友信息
1
2
3
4
因为大接口有如下四个缺点:

延迟更高,弱网环境下接口超时情况更多。
查看分析回包数据困难。
接口功能定位模糊,复用成本高。
更容易出错,出错时会卡住关键逻辑(登录)。
小结
总之,优化包体传输对于减小带宽占用、提升通信质量都有明显的好处。我们应该从缩减包体大小、减少推送消息数量两个角度做优化。对于包体大小要做适当的权衡,对于大量小包我们需要做必要的合并,而对于大接口我们应该做合理分拆,让每个接口独立做专门的事情。
————————————————

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1471277.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VB6添加资源文件总是内存溢出?最终我还是治好了这胎里病!

网管小贾 / sysadm.cc 说来也奇怪,话说不久前我刚刚解决了 VB6 释放资源文件的一个 BUG ,心里正美滋滋的。 不料居然还有个巨大的 BUG 在后边等着我呢! 真是不说不知道,一说吓一跳,十天找 BUG ,N把辛酸泪…

【国产MCU】-CH32V307-定时器同步模式

定时器同步模式 文章目录 定时器同步模式1、定时器同步模式介绍2、驱动API介绍3、定时器同步模式实例1、定时器同步模式介绍 CH32V307的定时器能够输出时钟脉冲(TRGO),也能接收其他定时器的输入(ITRx)。不同的定时器的ITRx的来源(别的定时器的TRGO)是不一样的。 通用定…

Python高性能web框架--Fastapi快速入门

文章目录 fastapi框架一、预备知识点1.1、http协议一、简介二、 http协议特性三、http请求协议与响应协议 1.2、api接口 二、quick start简单案例 fastapi框架 Fastapi,一个用于构建 API 的现代、快速(高性能)的web框架。 fastapi的两个核心…

单步调试Linux内核论证水位线

哈喽,我是子牙,一个很卷的硬核男人 深入研究计算机底层、Windows内核、Linux内核、Hotspot源码……聚焦做那些大家想学没地方学的课程。为了保证课程质量及教学效果,一年磨一剑,三年先后做了这些课程:手写JVM、手写OS…

Linux安装jdk、tomcat、MySQL离线安装与启动

一、JDK和Tomcat的安装 1.JDK安装 直接上传到Linux服务器的,上传jdk、tomcat安装包 解压JDK安装包 //解压jdk tar -zxvf jdk-8u151-linux-x64.tar.gz 置环境变量(JAVA_HOME和PATH) vim /etc/profile 在文件末尾添加以下内容: //java environment expo…

matlab一维二维和三维RBF插值方法

1、内容简介 略 50-可以交流、咨询、答疑 2、内容说明 略 3、仿真分析 略 matlab一维二维和三维RBF插值方法_哔哩哔哩_bilibili 4、参考论文 略

【Linux运维系列】vim操作

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

03-Linux权限

root用户 root用户(超级管理员) 无论是Windows、MacOS、Linux均采用多用的管理模式进行权限管理 在Linux系统中,拥有最大权限的账户名为:root(超级管理员)刚开始学习的时候,大多时间都是用的…

MySQL 篇-深入了解 DDL 语言(一)

🔥博客主页: 【小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍ 文章目录 1.0 MySQL 说明 2.0 DDL 语言 2.1 DDL 语言 - 定义数据库 2.1.1 创建数据库操作 2.1.2 查看数据库操作 2.1.3 使用数据库操作 2.1.4 删除数据库操作 2.2 DDL 语言 …

leetcode-hot100-双指针

剪枝,减少不必要的计算 283. 移动零 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2: 输入: nums [0] 输出: [0] 请注意 ,必须在不复制数组的情况下原地对数组进行操作。 第一印象:使用一个辅助数组,同时以…

蓝桥杯-答疑

原题链接:用户登录 答疑 题目描述 有 n 位同学同时找老师答疑。每位同学都预先估计了自己答疑的时间。 老师可以安排答疑的顺序,同学们要依次进入老师办公室答疑。一位同学答疑的过程如下 1.首先进入办公室,编号为 的同学需要 s,…

卖家横扫海外露营市场的机会来了,赛盈分销预测2024年消费者新需求

甲辰龙年开篇,就要迎来国外野营浪潮了,希望点开这篇推送的你,红红火火、热辣滚烫一整年。每年的3月份,海外用户对露营设备的搜索开始迅速增长。今天和大家聊聊露营市场出海的一些布局方向。 全球露营商品的市场规模愈发壮大&#…

Wireshark过滤DNS协议包语法实战

背景 现网DNS服务器发现CPU突增,发现有可能是客户恶意发起的随机子域名扫描,对服务器进行抓包分析,记录下当时的操作。 抓包 执行命令 tcpdump -iany port 53 and host $ip -nnv -w $ip.pcap进行抓包导出到本地,使用Wireshark进…

网站开发--详解Servlet

💕"Echo"💕 作者:Mylvzi 文章主要内容:网站开发–详解Servlet 一.基本介绍 tomcat是Java中开发服务器的重要的一个工具,任何开发的服务器都要部署在tomcat之上,可以说tomcat是所有服务器的底座,为了更好的操作http,to…

网络安全Web Hacking 101笔记,2023年最新整理!

在计算机技术如日中天的今天,Web安全问题也接踵而来。但Web安全却“入门简单精通难”,涉及技术非常多且广,学习阻力很大。 为此今天分享一份94页的《Web Hacking 101》笔记,包含Web安全知识,例如HTML注入、XSS、CSRF、…

MATLAB Function转C代码实战

文章目录 前言1. 准备工作2. 使用MATLAB Coder2.1 确定输入输出的类型2.2 MATLAB Coder过程 3. 代码调整和优化4. 编译和测试5. 性能分析和优化结语 前言 在科学与工程领域,MATLAB(Matrix Laboratory)是一种广泛使用的高级技术计算软件&…

Spring Boot 接口请求日志(基于AOP和自定义注解)

一、需求 在Spring Boot应用中,实现接口请求日志记录功能,要求能够记录包括请求方法、接口路径及请求参数等核心信息,并提供灵活的开关配置。 二、方案概述 采用AOP(面向切面编程)结合自定义注解的方式实现。 具体…

1904_ARM Cortex M系列芯片特性小结

1904_ARM Cortex M系列芯片特性小结 全部学习汇总: g_arm_cores: ARM内核的学习笔记 (gitee.com) ARM Cortex M系列的MCU用过好几款了,也涉及到了不同的内核。不过,关于这些内核的基本的特性还是有些不了解。从ARM的官方网站上找来了一个对比…

《游戏引擎架构》 -- 学习4

资源及文件系统 文件系统 游戏引擎的文件系统API通常提供以下功能: 搜需路径:是含一串路径的字符串,各路径之间以特殊字符(如冒号或分号)分隔,找文件时就会从这些路径进行搜寻。例如在命令行下执行程序&a…

2023年06月CCF-GESP编程能力等级认证Scratch编程一级真题解析

一、单选题(共10题,共30分) 第1题 以下不属于计算机输出设备的有( )。 A:麦克风 B:音箱 C:打印机 D:显示器 答案:A 第2题 点击下面哪个图标可以使舞台区…