游戏服务器开发指南(六):条件判断永远放在状态变更前

游戏服务器卡顿排查指南:从延迟丢包到优化实战 网络延迟与丢包是影响实时对战体验的核心因素,而游戏服务器性能则决定了玩家操作的响应速度与状态同步的稳定性。在竞技场景中,卡顿往往并非简单的网速问题,而是客户端到服务器链路上多个环节共同作用的结果。本文从延迟、抖动、丢包三个基础指标出发,结合客户端ping、tracert工具与服务器侧CPU、内存、带宽、慢查询等排查手段,系统梳理了从现象定位到架构优化的完整路径。无论是普通玩家自查家宽问题,还是开发运维人员分析服务端瓶颈,都能从中获得可落地的操作参考。文章同时覆盖凌晨定时任务、多游戏共用机房等隐蔽场景,并给出 阅读详情

大家好!我是长三月,一位在游戏行业工作多年的老程序员,专注于分享服务器开发相关的文章。

从这篇开始,我们进入到通用程序设计的主题。这个主题主要探讨如何编写高效、健壮、易读的业务代码。游戏的开发本质上还是以内容制作为导向的,业务代码的开发时间要远远大于架构设计和框架搭建的时间。而游戏服务器的业务又与互联网或者其他领域不同,有着自己的特点。这个主题会汇集多条从游戏服务器业务开发中总结的经验法则,每篇从一个小点切入,看似基础但实则重要。

本文是通用程序设计主题下的第一篇。关于编写健壮的服务器接口,有条很重要的原则是:条件判断永远放在状态变更前。

这条原则意思是为接口编写处理逻辑时,先罗列所有的条件判断,如果所有的判断通过,那么才进行状态变更(如更新DB或者修改内存状态),否则返回接口失败的信息给前端。例如下面从商店购买商品的代码:

public Msg buy(int playerId, int commodityId, int num) {
	if (!isCommodityIdValid(commodityId)) {	// 判断商品id是否存在
		return newFailMsg("错误的商品id");
	}
	if (!isCommodityEnough(commodityId)) {	// 判断商店中商品数量是否足够
		return newFailMsg("这种商品剩余数量已不足");
	}
	int costMoney = getCommodityCost(commodityId, num);
	if (!isMoneyEnough(playerId, costMoney)) {	// 判断玩家金币是否足够
		return newFailMsg("您的金币不足");
	}
	consumeMoney(playerId, costMoney);	// 消耗金币 
	deliverCommodity(playerId, commodity, num);	// 发送商品给玩家
	return newSuccMsg(playerId, commodityId, num);
}

这样做的原因很好理解:只有在所有的判断条件都通过后,状态变更(消耗金币和发货)才是合法的。而且消耗金币和发货这两个操作是相互关联的,适合放在一个原子操作中,要么同时成功,要么同时失败。试想,如果把对商品剩余数量的判断移到consumeMoney之后,那么可能会发生消耗了金币商品却没有到账的情况,这肯定是无法接受的。因此,将条件判断放在状态变更前,是为了保证状态变更的合法性和原子性。

另一种保证状态变更原子性的方法是使用数据库事务,但这里不推荐。原因是目前大部分游戏服务器为了实时性考虑,都倾向于把数据放在内存中,数据库事务无法针对内存中的数据变更做出事务性的保证。

有时候,为了追求代码复用,代码编写者可能会违反这条原则。这并非一定是因为疏忽,也可能是编写者有意为之,因为觉得状态的部分变更也是可以接受的。例如,原来有一个抽奖1次的程序:

public Msg drawLottery(int playerId) {
	int costMoney = getLotteryCost();
	if (!isMoneyEnough(playerId, costMoney)) {	// 判断玩家金币是否足够
		return newFailMsg("您的金币不足");
	}
	consumeMoney(playerId, costMoney);	// 消耗金币 
	Reward reward = doDrawLottery(playerId);	// 抽1次奖,奖励发送给玩家
	return newSuccMsg(playerId, reward);
}

后来需要新增10连抽的功能,为了代码的复用性,通过调用上面的代码10次来实现:

public Msg drawLottery10(int playerId) {
	Msg combinedMsg = newCombinedMsg();	// 组合消息,用于将单次抽奖结果拼装到一起
	for (int i = 1; i <= 10; i++) {
		Msg msg = drawLottery(playerId);
		if (msg.isFail()) {	// 如果本次抽奖失败,那么直接返回之前的抽奖结果
			return combinedMsg;
		} else {
			combinedMsg.add(msg);
		}
	}
	return combinedMsg;
}

代码编写者的思路是:通过不断重复单次抽奖,直到玩家的金币不够就会自然停止。但是,这种代码编写方式是不值得推荐的,因为会有以下缺点:

  1. 与玩家游戏直觉不符。玩家通常倾向于认为抽奖要么成功,要么失败,10连抽如果结果不足10个第一反应是游戏出了bug。
  2. 容易造成前端处理的混乱。上面代码会造成一种介于成功和失败之间的“部分成功”,前端对这种特殊情况如果处理不当,可能造成抽奖结果显示错误的问题。
  3. 为日志查询带来麻烦。假定方法doDrawLottery中包括对抽奖结果的日志记录,那么10连抽时会被分开记录成0-10条,彼此之间没有直接关联,如果需要区分10连抽还是单抽则会比较困难。

建议的改进写法是修改原有的drawLottery方法,将其改造成抽1次和抽10次都可以调用的通用方法,这样不仅保证了代码的复用性,还不会带来原写法的上述缺点。具体代码如下:

public Msg drawLottery(int playerId, int num) {
	if (num != 1 && num != 10) {
		return newFailMsg("非法的抽奖次数");
	}
	int costMoney = getLotteryCost() * num;
	if (!isMoneyEnough(playerId, costMoney)) {	// 判断玩家金币是否足够
		return newFailMsg("您的金币不足");
	}
	consumeMoney(playerId, costMoney);	// 消耗金币 
	List<Reward> rewards = doDrawLottery(playerId, num);	// 按指定次数抽奖,奖励发送给玩家
	return newSuccMsg(playerId, rewards);
}
游戏服务器和普通服务器的区别 背景 我做过六年游戏服务端开发,后来想换个方向,转做电商后端开发,做了两年之后感悟很多,也体会到了游戏服务器和普通的服务器的区别。 我所说的游戏是大众的游戏,它要有常见游戏的一些元素,比如交互,比如场景,比如对战。举几个例子:魔兽世界,梦幻西游,王者荣耀。 当然也有很多游戏是弱交互的游戏,其实这类游戏跟普通的服务器的区别会小一点。 其实游戏说到底,最重要的几点就是保持状态、低延迟、交互。这几点就让游戏服务器和普通的服务器(比如电商后端)区分开来了。 互联网和游戏后端开发的区别 游戏特有的 保持连接 游戏一般 阅读详情

相关推荐

ColyseusJS 轻量级多人游戏服务器开发框架 - 中文手册(下)

快速上手多人游戏服务器开发。后续会基于 Google Agones,更新相关 K8S 运维、大规模快速扩展专用游戏服务器的文章。拥抱☁️原生???? Cloud-Native! 系列 ColyseusJS 轻量级多人游戏服务器开发框架 - 中文手册(上) ColyseusJS 轻量级多人游戏服务器开发框架 - 中文手册(中) 状态处理 在 Colyseus 中,room handlers 是 有...

o__cc的博客 627

游戏服务器开发指南(目录)

本目录用于游戏服务器开发指南系列,分门别类存放文章的链接地址,方便读者快速索引。目录按不同的主题组织,如网络通信、数据存储等,每个主题会包含若干篇文章。个人计划是平均每周写一篇,写作基于平时工作中产生的灵感,因此不一定会按照主题的排列顺序来。

长三月的游戏开发 400

游戏服务器性能优化之架构设计篇

游戏服务器是一个复杂的分布式系统,其性能的优劣直接影响到玩家的游戏体验和运营的经济效益。微服务架构的核心理念是"高内聚、低耦合",即通过领域边界划分出很多独立的、细粒度的服务,每个服务专注于做好一件事情。不同的服务器可以根据其承担的任务配置不同的硬件和软件资源,避免了"一刀切"的资源浪费。传统的游戏服务器大多采用单服务器架构,即一台高性能服务器承担所有的游戏逻辑和数据处理任务。微服务架构作为一种新兴的、松耦合的分布式架构风格,为游戏服务器的开发和运维带来了新的思路。三、微服务化的游戏服务器。

qq_16714259的博客 2398

游戏服务器的那些事儿

https://www.fgba.net/sitemap.xml

august5291的博客 3545

新手必看:三大游戏服务器框架选型指南

游戏服务器框架是处理网络通信、数据同步和游戏逻辑的核心底层架构,其设计直接影响开发效率和最终性能表现。从技术原理看,现代框架通常采用状态同步或指令同步机制,通过WebSocket、UDP等传输协议实现实时交互。对于开发者而言,选择合适的框架能显著降低网络编程复杂度,特别是在处理高并发玩家连接和实时数据同步时。以Colyseus、Mirror等主流框架为例,它们通过内置的房间系统、序列化方案和心跳机制,为MMORPG、MOBA等不同类型的游戏提供基础支持。在实际开发中,开发者还需考虑网络抖动处理、反作弊验证等

weixin_34101914的博客 236

游戏服务器缓存系统如何设计

前言不管是在业界开源领域,还是内部分享中,很少会有专门针对游戏业务特征进行专门设计的组件、类库或者框架。我们从游戏的客户端方面来看,一款专业的游戏客户端引擎,已经是游戏开发的标配,flash,Cocos,Unity,Unreal等,但是服务器端,我们几乎找不到同样重量级的产品(当然有针对海外开发者快捷开发的服务器平台,比如GAE,GameSparks,PlayFab等能满.........

yolo模型训练找我,AI游戏合作找我 8万+

鹅厂公开课:游戏服务器,了解一下?

https://www.fgba.net/sitemap.xml

woliuqiangdong的博客 778

qPCR定量方法在肠道微生物特定种属定量应用

大家都知道肠道中有上千种细菌,肠道微生物可参与人体代谢,促进营养物质的消化吸收,肠道微生态均衡关系到身体健康,肠道微生态失衡可能会导致疾病产生。此外有文献指出肠道微生物可能与人体免疫及炎性反应等有关。目前也越来越多人关注到疾病与肠道微生物的关系,也做了很多研究及实验,一般高通量结果得到的是每个物种在样本中的相对百分含量,而不同微生物的绝对含量其实也对疾病有很重要的影响。在此分享几篇有采用qPCR方法研究疾病与肠道微生物关系的文章。 早在2013年Kim-Anne Lê1、Yan Li等人发表文章Alter

tinygene的博客 2143

游戏服务器的热更新与不停服架构:从 Lua 脚本注入到 Go Plugin 的模块级热重载方案

游戏服务器的热更新技术按复杂度分为三级:配置热加载(最安全,覆盖 80% 需求)、Lua 脚本注入(灵活性高,覆盖 15% 需求)、Go Plugin 模块替换(最复杂,覆盖 5% 的架构级需求)。三个层级的分层降低了对每种方案的技术风险——能通过配置解决的问题绝不用 Lua,能通过 Lua 解决的问题绝不用 Go Plugin。状态迁移是热更新的核心技术难点。protobuf 的序列化-反序列化快照配合版本兼容性管理(reserved 字段编号),可以将活跃战斗状态的迁移控制在 500ms 以内。

iymei4986533030的博客 4621

银河麒麟服务器操作系统V10 SP1:跨架构激活与设备更换无忧指南

本文详细解析了银河麒麟服务器操作系统V10 SP1的跨架构激活新特性。该特性彻底解除了授权与CPU架构的绑定,允许同一份授权在x86、ARM、龙芯等不同架构服务器间灵活使用。文章提供了从新设备激活到硬件更换后保持激活状态的全流程实战指南,并分享了内网环境部署等高级技巧,助力企业简化运维、提升硬件资源管理灵活性。

ff678的博客 352

TX 的 LOL(Local Oscillator Leakage,本振泄露)

项目内容LOL 是什么本振残留在 TX 输出中心频率上的杂散主要原因IQ 失衡、硬件不完美、零中频架构影响杂散、干扰、性能劣化、安全问题解决方法初始化校准 + 跟踪校准(AD9371 支持)检测手段频谱仪、回环检测、ADC ILA 抓取。

weixin_41230430的博客 2046

游戏的服务器号怎么查询网站,游戏服务器状态查询网站

游戏服务器状态查询网站 内容精选换一换网站的访问与云服务器的网络配置、端口通信、防火墙配置、安全组配置等多个环节相关联。任意一个环节出现问题,都会导致网站无法访问。本节操作介绍网站无法访问时的排查思路。网站无法访问怎么办?如果打开网站有报错提示信息,首先应该根据报错提示信息,排查可能的原因。您可以参考通用请求返回值中错误码说明排查可能原因。以下排查思路根据原因的出现概率进行排网站的访问与云服务器的...

weixin_36046832的博客 928

基于OkHttp3+Retrofit2+RxJava3搭建响应式网络框架

本文介绍了一个基于OkHttp3+Retrofit3+RxJava3的响应式网络框架设计。该框架采用分层架构,OkHttp3负责底层网络请求,Retrofit3封装HTTP接口,RxJava3实现响应式流处理。核心亮点包括:1)高度解耦的分层设计;2)统一的异常处理和响应体封装;3)RxJava3实现线程切换和请求管理;4)MVVM架构适配,业务层只需关注数据逻辑。框架提供了完整的实现方案,包括全局配置、拦截器、响应转换、接口声明、仓库封装等组件,并支持生产环境扩展功能如Cookie持久化、Token刷新等

fuge2008的博客 871

Colyseus 性能优化终极指南:10个方法大幅提升游戏服务器性能

Colyseus 是一款基于 Node.js 的多人游戏框架,专为构建高性能、可扩展的实时多人游戏服务器而设计。本指南将分享10个实用的性能优化技巧,帮助开发者充分发挥 Colyseus 的潜力,打造流畅稳定的游戏体验。 ## 为什么性能优化对 Colyseus 至关重要? 在多人在线游戏中,服务器性能直接影响玩家体验。高延迟、卡顿和连接中断不仅会让玩家感到沮丧,还可能导致用户流失。Colys

gitblog_00235的博客 838

UniApp实战:从文件下载到本地保存与预览的一站式解决方案

本文深入解析了UniApp开发中文件下载、保存与预览的完整流程,提供了基于uni.downloadFile、uni.saveFile和uni.openDocument API的一站式实战解决方案。文章详细拆解了核心API的使用方法、多平台(App、H5)的兼容性处理、常见坑点(如文件路径、权限、格式支持)以及进阶优化技巧(如进度提示、文件管理),旨在帮助开发者构建健壮、用户体验良好的跨平台文件处理功能。

d3e4f的博客 614

从零搭建医疗化验单识别系统:深度学习+OCR实战教程(附数据集)

本文详细介绍了如何从零开始构建一个医疗化验单智能识别系统。通过融合深度学习和OCR技术,系统能够应对版式多样、内容专业的医疗单据,实现从文本检测、识别到关键信息结构化抽取的全流程。文章提供了数据集处理、模型选型、训练微调及工程化部署的实战指南,并分享了避坑经验与性能优化策略,为开发者解决医疗信息化痛点提供了完整的技术方案。

k9l0m1的博客 492

使用 Agones 在集群外运行与调试本地游戏服务器(Out of Cluster Dev Server)

本篇技术指南围绕 Agones 的"Out of Cluster Dev Server"方案展开:在本地机器上直接运行游戏服务器二进制(支持 IDE 断点调试),同时让这个服务器作为集群内可分配(Allocatable)的 `GameServer` 资源,与完整的 Agones Kubernetes 栈协同工作。读完本文,你将掌握如何在本地运行 SDK Server(以 kubeconfig 连接

gitblog_01007的博客 1089

Python爬虫实战:如何通过解析JSON数据抓取抖音视频评论

本文介绍了如何使用Python爬虫抓取抖音视频评论数据。请求头伪造:通过使用随机的User-Agent,模拟真实用户的请求。代理池:使用代理IP来避免被封禁。JSON解析:直接从API接口获取JSON格式的数据,避免了动态加载内容的限制。需要注意的是,抓取网站数据时应遵守网站的爬虫协议,避免过度抓取影响网站性能或违反法律法规。希望本文能够帮助你掌握如何抓取和分析抖音视频评论数据!

2201_76125261的博客 3361

netty 游戏服务器 项目,netty游戏服务器源码

netty游戏服务器源码 内容精选换一换简要介绍KBEngine是一款开源的游戏服务端引擎,使用简单的约定协议就能够使客户端与服务端进行交互, 使用KBEngine插件能够快速与(Unity3D、OGRE、Cocos2d、 HTML5等)技术结合形成一个完整的客户端。语言:C++一句话描述:一款开源的游戏服务端引擎建议的版本建议使用版本为kbengine-2.5.2。云服务器要在本章节中,您将会把...

weixin_31445167的博客 1165

【QNX+Android虚拟化方案】129 - USB眼图参数配置

【QNX+Android虚拟化方案】129 - USB眼图参数配置

|~~~热爱生活、努力学习的小伙汁~~~| 821

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

游戏服务器异常修复,游戏服务器异常修复

游戏服务器异常修复 内容精选换一换您可以通过“应用管理”页面的应用列表,快速查看应用状态,及相关异常信息,如图1所示。包括:应用状态:即图1中的①应用异常信息:即图1中的②云服务器异常信息:即图1中的③本节详细介绍了应用及异常信息相关的状态类型及释义。即图1中的①,表示应用当前的情况,是否正常运行。应用状态的类型和释义,如表1所示。即图1中的②,记录了系统处理中发生异常,华为云帮助中心,为用户提供...

weixin_33712536的博客 497

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

网页游戏服务器搭建,如何搭建网页游戏服务器

如何搭建网页游戏服务器 内容精选换一换您可以在防护配额页面查看配额的使用情况、配额的状态,及时为即将到期的配额进行续费,或对没有使用额配额执行退订操作。配额列表仅显示在所选区域购买的配额,若未找到您的配额,请切换到正确的区域后再进行查找。绑定主机您也可以通过在主机管理防护配额页面的操作列中,单击绑定主机,为主机绑定防护配额,HSS自动为主机开启防护。一个配额只能绑定一个主机,华为云帮助中心,为用户...

weixin_35725821的博客 1637

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

2026终极指南:Colyseus游戏服务器框架的未来路线图与发展规划

Colyseus是一款高性能的游戏服务器框架,专为构建实时多人游戏而设计。它提供了可靠的网络同步、房间管理和状态同步功能,帮助开发者轻松创建沉浸式的 multiplayer 游戏体验。本文将深入探讨Colyseus的未来发展方向、即将推出的新功能以及技术优化路线,为游戏开发者提供全面的框架演进参考。 [![Colyseus框架Logo](https://raw.gitcode.com/gh_mi

gitblog_01017的博客 499

网页游戏服务器架设包,如何开架设网页游戏服务器

如何开架设网页游戏服务器 内容精选换一换目标服务器已安装操作系统,并且处于联网状态。目标服务器已安装鲲鹏编译插件。ECS的网卡绑定虚拟IP地址后,该虚拟IP地址无法ping通。以下排查思路根据原因的出现概率进行排序,建议您从高频率原因往低频率原因排查,从而帮助您快速找到问题的原因。如果解决完某个可能原因仍未解决问题,请继续排查其他可能原因。查看该网卡的“源/目的检查”是否关闭,虚拟IP是否已经绑定...

weixin_39963053的博客 1333

游戏服务器概述

声明:本文内容源自腾讯游戏学院程序公开课。 一、什么是游戏服务器 1,从游戏玩家之间的交互形态出发 单机游戏:一个人在机器上玩。 联网游戏:同时玩的范围比较小,比如8-10个人。 网络游戏:在远端有许多机器跑一个很大的系统,可以有几千几万几十万甚至更多的玩家连进来一起玩。 2,游戏服务是互联网服务的一种 常见的其他互联网服务有:搜索(百度)、电商(阿里)、即时通...

493

【Unity知识速递】第7期 Unity 6.6 深度解析:WebGPU 正式版与 WebAssembly64,Web 游戏的内存革命

如何启用 Wasm64?需要注意的是,Wasm64 需要浏览器支持 Memory64 提案,目前主流浏览器的最新版本都已支持。一句话总结: Unity 6.6 用 WebGPU 转正、Wasm64 16GB 内存和渐进式加载三连击,将 Web 游戏的体验天花板又往上推了一大截——Web 平台不再是"妥协版",正在成为真正的一等公民。Unity 6.6 新增了 WebAssembly64(Wasm64) 构建选项,这可能是本次更新中对 Web 游戏开发者影响最大的一项升级。

crystal_WJT的博客 425
上一篇: 近年GDC服务器分享合集(一):在《黑道圣徒》的boss工厂中创建可扩展和吸引人的UGC
下一篇: 近年GDC服务器分享合集(二): 《太空工程师》中基于预测物理的多人游戏
长三月
博客等级 码龄9年 228粉丝 80原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值