![](https://img-blog.csdnimg.cn/20190918140129601.png?x-oss-process=image/resize,m_fixed,h_224,w_224)
思考
思考
.net core game
致力于.net core全栈游戏服务器开发
展开
-
再次思考:xdb和无锁2种设计方案
以:排行榜结算为例子,那么上榜逻辑,根据榜单类型,始终到这个榜单所在的线程,那就没什么问题。这样子直接搞就行,其实想想,如果是:使用redis来做,redis本身就是单线程的,其实也都差不多,在redis服务器这里,都是挨个执行队列中提交过来的redis命令。其实xdb解决的就是:一旦出现了数据同时访问的情况,那么锁互斥就有作用了,对这个数据的访问只能有一个线程进来。而无锁方案,则是:路由到一个固定线程,现在想想,其实也没什么区别了。TYPE_2(2, "排行榜类型2"),原创 2022-09-15 17:14:42 · 215 阅读 · 0 评论 -
思考:普通的maven工程与spring项目的融合
由于咱们自己的游戏服务器有可能要接入别的组件,别人的组件有可能以Starter的形式启动,这个时候,我们可以考虑将自己的工程也能接入第三方starter,如:oss文件上传。其实也很简单。只需要新建SpringBoot工程,然后将之前main函数的工程代码移动到SpringBoot工程中的CommandLinster中即可。其它的以来的starter组件,标记为spring组件,然后通过SpringUtil的方式通过class名字即可导入到咱们自己的Service组件中。 这样子就实现了2类工程的融原创 2022-04-18 14:04:17 · 2101 阅读 · 0 评论 -
思考:【mongodb+redis】遇到的问题及其解决方案
1.事务的问题如果是mysql,一般的设计是在处理玩家数据时,一个业务内操作多张表,如果有一个操作失败,则所有的数据回滚。mongodb的话,无法回滚,针对这种问题的解决方案是:操作mongodb,其实在落地前,是存放到临时的json中,如果操作业务异常了,那么就也不会落地,这样子变相解决了事务的问题。2.mongodb和redis不一致的问题如果是mysql,一般是:使用mysql的binlog,实现最终一致性。mongodb则没有这些,我们解决方案是:由于mongodb存储业务尽量用原创 2022-03-28 10:44:37 · 1181 阅读 · 0 评论 -
战斗的设计
1)现在看了公司的战斗分享才突然明白,其实战斗的设计是有套路的。 策划的思考 与 程序的实现,其实是有鸿沟的。2)战斗的设计有一些技巧,拿es发射w技能达到提莫来说,如何设计这个功能呢?首选是技能、子弹发射器(es的w)、buff(提莫身上的光圈)。3)逻辑上的串行执行让简化设计:看起来你打我,我打你好像是并行的,实际上游戏引擎中一定是串行执行的。EZ w技能打到提莫,和提莫用Q技能打到EZ,其实逻辑上最好是串行执行。比如:先更新子弹,再更新buff等,最后计算伤害。...原创 2021-10-11 12:04:22 · 163 阅读 · 0 评论 -
客户端数据 和 服务器数据 的信任关系
1)基本原则客户端相信客户端。服务器相信服务器。客户端收到服务器信息,更新即可,总是认为服务器发来的数据是正确的。2)一个背包问题的实战:比如:背包系统。 服务器推送了所有的背包数据,那么客户端初次展示背包内容。假如:背包中物品A有10个,当客户端发起售卖请求卖了5个A时,客户端的背包如何刷新呢?方法1: 客户端removeAllChildren所有的背包数据,从而从新请求背包数据从而刷新UI。方法2:客户端发起售卖,服务器告诉售卖成功,数量变化为5,客户端从本地存储..原创 2021-03-12 15:21:56 · 248 阅读 · 0 评论 -
消息基本消息设计原则: 服务器的消息驱动客户端的UI显示
消息基本消息设计原则: 服务器的消息驱动客户端的UI显示。以 ‘五子棋’为例子,服务器分配给客户端座位号,轮到谁则是服务器驱动着走。原创 2021-04-11 10:38:24 · 146 阅读 · 0 评论 -
思考:实际中遇到的2个需要重构的问题: 1.普通mj场扩展出金币场 2.一种mj玩法,扩展出20多种玩法
(1)从普通麻将场扩展出金币场 1.抽象出 普通麻将和金币场的相同接口 和 在金币场上新增接口, 利用继承去扩展, 动态添加对应的组件。(2)麻将app,开始有1种玩法, 后来有20种玩法 1.简单粗暴的方法: 大量的if else。 2.较好写法的思考: 写好继承关系, 利用代码, 添加组件(未实践)....原创 2021-03-12 16:13:01 · 74 阅读 · 0 评论 -
cocos creator 1.不销毁节点 2.加锁解决网络消息没监听的问题
1)代码let websocket = cc.Class({ extends: cc.Component, properties: { _sock: null, _services_handler: null, _msg_queue: [], is_lock: false, }, onLoa...原创 2019-12-20 15:20:04 · 1415 阅读 · 0 评论 -
单场景+update分发消息 网络游戏客户端架构设计模式可靠性证明
1)网络模块在websocket收到消息,不是直接 evt.getInstance().emit("msg"+ msgId, msgData); 这样发不出来,而是扔到socket组件的消息队列msg_queue,在一个组件的update里面进行抛出消息。解决的问题: 避免切换场景时,觉得:服务器消息发过来了,但是我在切换场景,没有处理。2)ui模块切换场景其实不再是切换场...原创 2019-07-12 11:48:34 · 286 阅读 · 0 评论 -
服务器中的单例模式:启动时就进行初始化
IInit.javapackage org.example.testsingleton;public interface IInit { void init();}Main.javapackage org.example.testsingleton;import org.reflections.Reflections;import java.util.Set;public class Main implements IInit { public stati原创 2022-01-04 10:49:40 · 431 阅读 · 0 评论 -
数据包长度计算
为了让框架更加紧密,单独独立出来Game模块。IOHandler等处不同 语言不一样,但是解析出:服务端:数据长度(2+2+2+4+body长度) + stype(2个字节)+ctype(2字节), uid(4字节), body(n个字节)客户端: 数据长度(2+2+2+4+body长度) + stype(2个字节)+ctype(2字节), 占位(4字节), body(n个字节)这样独立出来MsgDispatcher模块进行消息分发,更加明确,然后里面进行EventMgr进行消息抛出来...原创 2021-01-18 19:06:28 · 992 阅读 · 0 评论 -
mysql和redis双写一致性的问题
1)领导一直再提:mysql在写,redis也在写,会出现双写一致性的问题。2)并简要给了个方案: 每次mysql写入时就删除redis缓存,读的时候没读到,就从mysql加载并写到redis。原创 2021-11-11 10:09:38 · 715 阅读 · 0 评论 -
观察者模式应用之任务系统的设计
任务都有一个taskId, 在人登录成功时,开始初始化身上的任务,对于已经完成的任务,就取消掉监听,未完成的任务,是有监听。以杀怪为例子,一个任务是:杀死10只怪,那么杀怪后,就fire一个事件,至于是否计数,完全是看之前注册的监听器的状态,之前完成过了,那fire也不会计数。这样子使用taskId就把各种任务区分开了。...原创 2022-01-14 16:11:18 · 211 阅读 · 0 评论 -
尝试抽象出来一个房间桌子功能
1)背景假如我作为服务端维护着20个项目,那么我就可以用模板方法提供这样一个算法框架自己写一个默认的实现,利用js动态语言的特性,然后把具体功能交给其他人实现,自己调用即可。2)实现// 1.服务器抽象出来一个桌子和channel关联起来function AbstractTable(channel) { this.channel = channel;}Abstract...原创 2019-04-01 23:42:04 · 339 阅读 · 0 评论 -
参考CopyOnWriteList思想:实现DbService多线程持久化并发安全
1)问题分析数据库的持久化是会产生IO操作的,因此不应该放在业务线程,但是如果放在DB线程持久化数据,那么又会带来线程安全的问题,比如:class Role{private Map<String, HeroModel> heros;private Map<String, ItemProp> items;}那么在DB线程操作,heroes不是线程安全的,势必带来线程安全问题。2)实战我们在项目中是采用mongodb进行数据...原创 2021-08-16 10:21:02 · 151 阅读 · 0 评论 -
思考:从xdb的线程模型思考线程安全的设计方案
1)思考2个常见的问题 1.每日登录这种人与系统的交互。 2.你给我转账的同时,我也给你转账。 3.排行榜上,2人交换名次。 4.大家到一个匹配队列进行斗地主匹配,匹配到了开房间打一局斗地主。匹配队列。2)常见的线程模型有:无锁和有锁的3)现在讲有锁方案: (1)人与系统查询 和 进行领取操作一定是分开的。 查询不用在事务中,因此只用select即可。 领取是修改了数据库,在get的时候,...原创 2021-11-11 10:22:21 · 440 阅读 · 0 评论 -
我眼中的比较通用的任务处理的并发模型: 银行排队处理客户业务
1)并发的线程模型有很多种,比如:skynet的actor模型,但是经过深入的思考,发现还是netty这种无锁化设计是最适合逻辑组织,也是最简单的。2)代码就是人生,转化到现实中,那么就是银行的排队系统:8个窗口(8核的机器),那么来了100个客户端,那么我并发就是同时处理8个任务,让100个客户手中都拿一个号码:0~99,0号由窗口0处理,1号由窗口1处理... 这样客户足够多,那么8个窗口都在处理客户业务,都没有闲下来。这就是相当于充分利用了多个CPU核心。3)虽然理论上比actor损失了一原创 2021-02-20 14:32:54 · 239 阅读 · 2 评论 -
思考:服务器设计文档的重要性及其如何编写
1)背景我们在开发功能过程中,有时是完全自己设计,有时是在别人代码基础上设计,有时候不知道大家有没有一种感觉:连自己设计的代码,自己都说不清楚。我思考之后,总结了下,这个问题其实是因为:自己没有从头梳理一遍。为了解决这个问题,才有个这个文档设计doc的编写。开发都很忙,那么我们何时编写这个doc呢? 我想应该是在功能开发完成后,因为此时,我们才需要梳理自己的思路。2)如何编写?1.业务理解这个是用自己的语言描述下对这个开发过的模块的理解及其注意事项。2.消息号由于服务原创 2021-10-11 11:59:50 · 173 阅读 · 0 评论 -
思考: 1.账号表(Account) 角色表(Role)分离
sql/*Navicat MySQL Data TransferSource Server : localhostSource Server Version : 50723Source Host : localhost:3306Source Database : doudizhuTarget Server Type : MYSQLTarget Server Version : 50723File Encoding原创 2021-09-08 18:24:00 · 683 阅读 · 0 评论 -
【3类业务系统设计】人与系统、人与人(好友)、人与人集结版本(组队、房间、工会、地图)
1)好友的添加删除,由于业务经常需要单线程操作,但是好友 这种却没有一个集结玩家的地方,因此我认为即使使用redis,如果没有投递 到指定线程操作,其实也会出现问题,只不过这种业务出了问题影响不大而已,比如:addFriend(rid1,rid2);xxxaddFriend(rid2, rid1);delFriend(rid1,rid2);xxxdelFriend(rid2, rid1);由于每步操作都不是原子操作,可能会出现:一个人有另外一个人的好友,但是另外一个人却不在别原创 2021-09-08 14:29:50 · 77 阅读 · 0 评论 -
思考: 服务器代码目录结构规划
1)4类服务器类型 globalserver: 账号服务器、分区分服负载维护 gameserver: 玩家自己的数据 worldserver: 玩家之间交互采用单线程写业务逻辑 rtsserver: 要求实时很高的直连2)handler(接收玩家请求)3)service(所有服务接口,服务之间调用只有service)4)logic(具体的一个个业务,里面采用Manager是具体的实现) xxx1 xxxManager //...原创 2021-09-11 11:07:07 · 270 阅读 · 0 评论 -
思考:游戏服务器中“网络和数据库 ”2个模块的架构思路
1)One Loop Per Thread(以8核心16G内存为例子)1个线程主Reactor: 负责accept新的链接。16个线程的从Reactor:负责很多个socket的IO读写事件。8个业务线程:负责收到IO事件后,进行业务处理,里面都是同步的写逻辑。4个DBThread:在业务中进行数据库异步 落地时使用。4个RPC Thread:负责多个系统之间的rpc通信。总结:掌握这一种高并发的模型即可,可以看出: 线程数量固定,不会膨胀,会比较稳定。...原创 2021-09-15 10:05:08 · 164 阅读 · 0 评论 -
游戏服务器框架maven工程组成模式(参考zfoo): framework+具体游戏
1)framework是一个独立的maven工程,里面有很多module2)具体游戏是一个具体的游戏,如:tank或zapp3)在具体游戏中maven add添加下framework的依赖,这样子让具体游戏不会编译报错,但是又可以做到强制framework独立出来。...原创 2021-11-17 13:11:20 · 2514 阅读 · 0 评论 -
【游戏服务器设计案例篇】感悟
1.记录index,而不是具体的内容。2.分为登陆时的处理 和 凌晨5点的处理原创 2021-12-18 18:50:06 · 2462 阅读 · 0 评论 -
思考:再次理解get和post
之前面试有问到:get和pose的区别,我说:项目中一般用post就足够了。但是了解了es的操作,发现里面对restful用的淋漓尽致,其实get和post还有一种区别是:幂等性。比如:get,无论多少次,那么都是幂等的,每次都是一样的结果。但是post则不是。...原创 2021-12-21 12:22:04 · 452 阅读 · 0 评论 -
ghost和ctrl分离的方式处理同步设计
Ghost和ctrl分开的设计思想用于多人状态同步。那么:棋牌的也可以。自己和别人的区别在于,大家都有Ghost,也就是显示。Ctrl: 是发出动作,自己的有这个组件,别人的没有这个组件而已,其余的完全相同。...原创 2021-03-12 15:15:55 · 109 阅读 · 0 评论 -
思考:服务器架构的演进
1.1个进程,1个txt文件,N个玩家2.1个进程,1个mysql,N个玩家3.多个网关,多个中心服(玩家个人数据),多个地图服(玩家之间的交互,一起打怪pk)4.无缝大地图架构(每个地图对应一个进程,可以相互传送,就好像在有一个无限大的地图中一样,魔兽世界这种)---------------------Java:回调c#:带有await和async的协程,而且是:单线程中的协程。---------ET的架构理解:1个网关负载均衡服务器(玩...原创 2021-12-21 12:38:52 · 1195 阅读 · 0 评论 -
思考:优先使用组合而不是继承 1.继承的耦合程度最高? 2.多态?
1) 场景当然需要在普通的房卡模式中加入比赛场模块,玩法A B C D...很多种玩法,他们都是房卡模式,继承了一个公共的父类Base,此时需要加入比赛场,使用的是lua语言。2) 继承还是组合?有2种方法:1.可以写一个类MatchGameScene动态继承A B C D玩法类2.在Base中写个模块,组合的方式,挂载在Base上,当不是比赛场,那么不开启这个模块。3)总...原创 2019-03-14 12:30:56 · 612 阅读 · 0 评论 -
思考:要学会记录日志
之前做客户端其实都是在写debug日志,比如:当打的包崩溃了,那么才根据崩溃的包查询原因。服务器的话,不仅平时写功能时需要记录日志,比如:QA发现有问题时,我们需要根据日志进行问题排查。上线后,需要根据日志文件进行问题排查。哪些东西需要记录日志呢?比如:玩家升级、获得道具时的数据...等关键性的东西进行排查。记录日志,一定要打印出关键的参数信息。...原创 2022-01-04 10:27:13 · 152 阅读 · 0 评论 -
思考: 为什么单元测试如此重要,如何写符合单元测试的代码
单元测试这块其实很多人是不重视的,如今我才意识到单元测试的重要性,实际开发中,我说的单元测试并不是说:你写的代码都要用java下的test一个个进行测试。而是说:自己写的代码要 符合单元测试规范。我们作为服务器,大部分情况下其实就是为客户端提供接口,并处理完数据返回给他,因此模块设计如下:handler // 接客户端请求service // 服务处理入口类,统计客户端的请求参数。 对外暴露的接口。logicmanager // 业务逻辑类...原创 2021-09-30 11:20:25 · 111 阅读 · 0 评论 -
思考:什么是异步与线程安全
1)异步情况下:1.在线程1发起查询请求2.阻塞线程2等待结果3.线程2拿到结果,并把结果push到线程1的队列中。。。假如是:线程1发起了100次请求,可以看出,一定收到的也是顺序返回的。2)再思考同步:线程1发起func call,然后直接拿到结果。假如是:线程1发起了100次请求,可以看出,一定收到的也是顺序返回的。总结:这么看来,对于一个数据的处理,其实虽然是异步的,但是从最后的调用结果来看,跟函数调用没什么区别!...原创 2022-02-19 15:43:39 · 449 阅读 · 0 评论 -
思考:以卖票为例子思考Actor模型(3种卖票方案对比)
假如票有100张,多线程卖票,如何保证并发 安全 呢?1)常见思路(单体)比如:保证 多线程对于票的修改是线程安全 的。 因此:需要加锁。在 每个线程修改的地方synchronized(ticket){// 检测票是否足够// 足够则通知发货}2)actor模型TicketActor: 票actor,维护票数,只有它有修改的权利。PlayerActor:有多个,想要卖票 ,先向TicketActor发起询问,TicketActor查询票是否足够,够了则通知下单。原创 2021-10-30 11:55:18 · 1133 阅读 · 0 评论 -
思考: 乐观锁的3处使用
1.ABAcompare and swap中,有可能在修改后,又还原了, 则不知道是否发生了更改,因此每次更新加上版本号,则知道。2.mysqlselect xxx where 条件; 比如在秒杀中,通过这样的sql,保证在有商品时,才能购买,避免超发。3.eses中通过版本号确定你本次操作是否能进行,在想修改时,先比较版本号,如果不是最新,则不能修改。...原创 2021-11-28 13:24:13 · 433 阅读 · 0 评论 -
再次思考:A和B相互转账的问题
1)xdb方案根据a和b获取uid,然后uid排序后加锁。 这样子保证了同一时刻只有一个线程能对这个玩家的数据进行‘’修改‘’操作。2)队列方案由于涉及2个玩家,那么获取2个玩家的数据后,如果在A的线程获取B的数据,那千万不能此时修改B的数据,而是只能只读操作。 进行一些校验等,满足条件后,进行修改数据时,一定要回到B所在的线程进行操作。...原创 2021-12-09 09:46:32 · 211 阅读 · 0 评论 -
思考:简单理解下SpringBoot自动配置的原理
1.@SpringBootApplication注解是要标记在启动类上,这是一个复合注解,其中有个是自动配置的注解。2.@Import 会导入一个Bean3.在初始化 某个Bean时,就进行了确定了启动类所在的jar包。4.同时会扫描spring.xml中下面的类。再根据条件装配,从而确定是否开启,因此我们可以根据这个条件装配的特性,实现自己的Starter5.依赖于xxxOnMissBean这个,从而实现当我们导入某个jar包时,某个功能才会开启,否则压根不会开启,从而SpringBoot原创 2022-01-24 11:37:45 · 90 阅读 · 0 评论 -
思考: 游戏服务器中Excel导出工具制作应该考虑的几个需求
1.表格中支持json是非常方便的,比如可能有10个种类的活动类型,每个活动由于是不同的玩法,所以数据结构和字段必然不同;2)这时除了配置好公用的activityType外,数据相关的就可以使用json,这样子程序必然是知道如何解析这个活动相关的数据的,而不是都做成一行中只有简单数据类型的结构。...原创 2021-09-17 15:46:40 · 131 阅读 · 0 评论 -
思考:流程图+伪代码用于分析复杂的逻辑
有时候一个系统非常复杂,已经不能在头脑中直接运行代码了。这时可以画一下流程图+伪代码的形式写出代码,然后再翻译为实际的java代码。原创 2021-12-22 00:40:54 · 551 阅读 · 0 评论 -
思考:为何web服务器每次都要查数据库 而 游戏服务器则是定时存储
答:1)因为web应用涉及到的数据没有在内存中存储,都是短连接的http,因此不得不每次查询和修改都是要经过一次IO直接从数据库中load。同时为了标识出用户,因此需要token等信息,不用每次都发送账号和密码,而是直接下次从header中发送即可,这样子就可以从token中直接解析出用户。2)而游戏服务器要求更高的实时性,都是长链接,服务器也能直接的推送数据给客户端,为了减少io次数,必须要不卡主业务线程,即使是落地,也是在别的线程,采用copy on write写时复制的思想,这样子在业原创 2022-01-14 10:32:09 · 2274 阅读 · 0 评论