传统软件服务器与游戏服务器架构区别

2023-05-16

项目智能客服爬虫SLG游戏
语言javapythonkotlin
模型异步事件驱动可能没什么模型可言actor模型
传输协议httphttptcp + netty
传输结构jsonjsonprotobuf
数据库oracle,redismongodbmysql,redis
数据库框架mybatispython库(类似jdbc)hibernate
缓存架构管理员登录状态用redis可能只缓存了页码所有游戏用的数据全部缓存,每隔一段时间写到数据库中
配置信息只有application.propertiesconfig.inizookeeper,启动前需要将策划表信息刷到zk
并发无并发(所以根本没用到锁)python多线程同时爬多个网站无并发actor模型保证一次只做一件事
热更直接重启继承某个类的某个方法,替换掉线上的类

架构一览

智能客服服务端整体架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g2fYVHkG-1650104096072)(./images/智能客服服务端整体架构.png)]

SLG游戏整体架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5xMLFal4-1650104096073)(./images/SLG游戏整体架构.png)]

典型案例

智能客服聊天

http聊天消息
将聊天信息放入mq
问答信息记录
客户端
智能客服系统
智能问答模型
Oracle数据库

SLG游戏士兵出征

tcp发送的protobuf
actor内部消息转发
actor内部消息转发
客户端
Gate的Netty解包
WorldActor校验外城沙盘各种状态
playerActor内城校验和获取buff

其中worldActor和playerActor都通过读取内存的方式读取到需要的数据,并不直接读取mysql数据库。
内存里的数据每隔一段时间(30秒左右)将变化的数据通过hibernate的方法更新到mysql中。

配置信息读取

对于智能客服来说,由于并发量业务量很少(因为投放的平台比较少,且晚上凌晨基本没什么人使用,且重启速度很快),有一些需求上的配置数值(比如发送几次“转人工”才进入转人工通道)是直接硬写在业务里的;也有一些配置信息是其他系统的请求地址url,会配在application.properties里。没有使用excel统一存储各个功能模块的配置信息,也确实不需要。

但对于游戏来说,数值这块的配置至关重要,与玩法,奖励,游戏内生态息息相关。因此在游戏服务器里,所有的数值几乎都要从配置表中读取。目前Excel应该是处理数据能力最强的软件了,策划可以通过Excel非常快速的把数值配好。
启动服务器的时候要读取配置表到内存(广义上的)里。但在有了zookeeper这样的工具出现之后,配置表数据可以放在zk中,需要的时候再取出来。

游戏服务器优势

传输结构为protobuf

服务器接收和发送的数据都是ProtoBuf转成的二进制,从而实现客户端服务器端统一的传输结构。protobuf自己有编码解码二进制的功能,从而实现消息数据的大小达到最小,编码解码是由netty执行的,使用上只需要将protobuf生成的对象传给netty即可。这边用的protobuf是v2版本的,有required,optional和repeated三种关键字,分别对传输message里的属性作出了约束。

Akka Actor架构

Actor架构实现单线程的业务逻辑,开发过程中不需要对一些公用的属性上锁;通过内部消息的通讯,让数据处理有序进行。Akka cluster集群有动态负载均衡的功能,可以进行平行扩展,也就是说,如果一台服务器扛不住并发,只要再配置一台或几台新服务器,加入集群就可以完成负载均衡。

配置表信息Zookeeper存储

通过将Excel数据表信息读取到java代码中,再转成二进制放入zk里,随时读取,从而完成了配置表的热更新。

数据在服务器启动后,缓存在内存中,间隔一定时间刷入库中

游戏服务器不直接操作数据库,而是操作内存中的数据。内存中的数据每隔一段时间,将数据变化更新到数据库中。如此一来,并发IO特别大的时候,也只是对内存中的数据进行修改,不会直接操作数据库。

两个系统中存在的问题

智能客服

抽取报表时直接用Oracle关联查询,效率太低,且没有读写分离

智能客服的报表是实时的,是通过一个特别长的,用union拼接的sql写的。所以查询速度非常慢。在线上环境,选定一个超过14天的时间区间,勾选多个报表评估项,查询时间超过30秒。也就是说sql执行了近30秒。当时一直说要优化优化,但是最后也没想出什么办法。

后来我也接触了一些报表,一般是将生的,未处理过的数据通过消息队列发给另一个日志收集库,可能会叫它数据仓库。然后另外有一个系统从数据仓库里抽取并统计数据。
另一种是抽取报表时只查询今天以前的数据,然后每天结束时24点之后执行某一个定时任务,统计更新报表数据。

当然了这些举措都导致了不能实时展示最新报表数据了,这也是一种取舍。

聊天记录日志设计不合理

聊天记录表每一行记录都包含了发送人和聊天会话的各种信息,存储了过多的状态(因为存在聊天记录评价这种特殊消息,所以结构发生了很大变化)。
有可能是最初只考虑了文字,后面加入了图片(支持html又有html注入风险),后面又出了“猜你想问”气泡,但猜你想问本身不计入聊天记录,又需要特殊处理。

由于没有安排重构,导致开发到后期,前后端代码都非常混乱。

SLG游戏服务器

热更问题

项目越庞大,遇到的问题就会越多。问题越多,修复更新到线上的速度当然要越快越好。得益于java的继承功能,我们可以通过继承某个装有业务逻辑的类,重新重写某个之前有问题的函数,修正为正确的业务逻辑,以完成线上玩家无感知的热更新。但是这并不能完全覆盖每一个线上问题。除了业务逻辑类之外,还有数据处理存储类,而数据处理存储类是不能热更的,因为它们是与定时落库逻辑强关联的类。有的业务逻辑被开发人员写在数据处理存储类中,就不能热更修改了。
还有一些属性被加上了private标识符,导致没办法直接取出来,只能用反射拿。

节点之间通信

Akka Actor是单线程,但不意味着整个系统都是单线程的。为了提高效率,我们根据业务逻辑,按照功能模块,分出了维护不同数据的Actor,比如网关Gate,外城沙盘World,内城玩家本身Home,联盟Alliance,全服排行榜Rank…但是这么一来,会有一些本应该由多个节点共享的数据,不得不需要用服务器内部消息来回同步。

比如说有一个运营活动,是关于某个人打沙盘上的某个怪,然后给自己和联盟增加积分。那么这时候,World,Home,Alliance三个节点都需要各自保存一份活动的开启时间和关闭时间。当然还有一种办法,是在zookeeper上分配一个json对象,存储当前的活动信息。但是这么一来,如果所有比较复杂的活动都使用这种方式,到最后zookeeper会存储过多的不常用的数据。

其他系统

智能客服边缘系统:知识库系统

本来的目的是将智能客服的语料信息单独抽出作为一个独立的子系统,但后来由于语料信息与智能客服本体关联太紧,导致没有办法抽出来。

为了实现模糊查询,使用了es作为存储数据库。
其中存在一个问题,就是关系型数据库与非关系型数据库的矛盾之处。
大概是用关系型数据库可以方便管理数据,减少数据冗余,但失去了es模糊查询倒排索引的能力。
但直接用菲关系型数据库的话,会让系统中其他数据库的表无法直接关联,被迫需要用服务的方式来获取资源,增加系统开销
如果在关系型的oracle和非关系型的es各存一份,则会出现数据不同步的问题,被迫需要定时任务去同步两个库,甚至还需要从两个库中作出鉴别,类似于git,svn等做版本管理。

游戏服务器:运维GM

  • 发送补丁到线上服务器,替换线上服务器的某个类的某个方法的实现,从而完成玩家无感知的热更新
  • 发送groovy脚本到线上服务器,在线上服务器上执行一段通过groovy编写的业务逻辑
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

传统软件服务器与游戏服务器架构区别 的相关文章

  • jni/ndk问题 :引用so库报错: java.lang.UnsatisfiedLinkError: No implementation found for

    问题 xff1a 引用so库报错 xff1a java span class token punctuation span lang span class token punctuation span UnsatisfiedLinkErro
  • 《python+opencv实践》一、基于颜色的物体追踪(上)

    点击打开链接 本文主要参考国外一大牛博客 xff0c 然后自己修改得来 相关知识点在这里 实现功能 xff1a 追踪红颜色瓶盖 xff0c 并画出瓶盖轮廓和运动轨迹 from collections import deque import
  • C++的sort函数实现字符串排序

    一 背景 sort函数用于C 43 43 中 xff0c 对给定区间所有元素进行排序 头文件是 include lt algorithm gt 实现原理 xff1a sort并不是简单的快速排序 xff0c 它对普通的快速排序进行了优化 x
  • C# 中的Dispose()用法

    一 对Dispose方法的理解是什么呢 xff1f 使用Dispose方法的对象 xff0c 应释放它拥有的所有资源 它还应该通过调用其父类型的Dispose方法释放其基类型拥有的所有资源 net的对象使用一般分为三种情况 1 创建对象 2
  • C++的 remove函数

    一 介绍 remove函数原型如下 xff1a template lt class ForwardIt class T gt ForwardIt remove ForwardIt first ForwardIt last const T a
  • 主板上的南桥与北桥

    一 历史 曾经 xff0c 北桥芯片和南桥芯片都是主板芯片组中最重要的组成部分 传统来说 xff0c 靠上方的叫北桥 xff0c 靠下方的叫南桥 北桥负责与CPU通信 xff0c 并且连接高速设备 xff08 内存 显卡 xff09 xff
  • CMake的add_library与target_link_libraries

    一 add library介绍 使用该命令可以在Linux下生成 xff08 静态 动态 xff09 库so或者 a文件 xff0c Windows下就是dll与lib文件 xff0c 它有两种命令格式 1 1 第一种格式 xff1a No
  • Linux下终止正在执行的shell脚本

    一 问题 Linux系统Shell中提交了一个脚本 xff0c 但是需要停止这个进程 xff0c 如何处理 xff1f 二 方案1 killall fileName 说明 xff1a killall是一个命令 xff0c 不是kill al
  • Qt对象树的销毁

    一 问题 在C 43 43 中中 xff0c 我们都知道 xff1a delete 和 new 必须配对使用 一 一对应 xff1a delete少了 xff0c 则内存泄露 为什么Qt使用new来创建一个控件 xff0c 但是却没有使用d
  • DNS域名解析之递归与非递归查询

    DNS域名解析之递归与非递归查询 递归查询迭代查询实例 递归查询 主机向本地域名服务器的查询一般是递归查询 xff1a 如果本地域名服务器不知道查询的IP地址 xff0c 那么本地域名服务器就会以DNS客户的身份向根域名服务器继续发生请求
  • spi,iic,uart,pcie区别

    一 spi SPI 是英语Serial Peripheral interface的缩写 xff0c 顾名思义就是串行外围设备接口 xff0c 是同步传输协议 xff0c 特征是 xff1a 设备有主机 xff08 master xff09
  • 决策树的介绍

    一 介绍 决策树 decision tree 是一类常见的机器学习方法 它是一种树形结构 xff0c 其中每个内部节点表示一个属性上的判断 xff0c 每个分支代表一个判断结果的输出 xff0c 最后每个叶节点代表一种分类结果 例如 xff
  • 支持向量机

    一 是否线性可分的问题 考虑图6 1中 xff0c A D共4个方框中的数据点分布 xff0c 一个问题就是 xff0c 能否画出一条直线 xff0c 将圆形点和方形点分开呢 xff1f 比如图6 2中 xff0c 方框A中的两组数据 xf
  • cmake 链接库名称扩展

    多个文件 macro span class token punctuation span configure lib by types OUTLIBS DebugSuffix span class token punctuation spa
  • 如何自定义TCP通信协议

    物联网行业智能硬件之间的通信 异构系统之间的对接 中间件的研发 以及各种即时聊天软件等 xff0c 都会涉及自定义协议 为了满足不同的业务场景的需要 xff0c 应用层之间通信需要实现各种各样的网络协议 以异构系统的对接为例 在早期 xff
  • 使用米联客FPGA开发板 固化程序失败

    问题描述 xff1a 使用米联客FPGA ZYNQ7020开发板 xff0c 在利用工程和FSBL生成BOOT bin和fsbl elf文件 烧录FLASH时 xff0c 总是失败 这个问题折腾我小半天 xff0c xff0c 无语了 后来
  • Qt串口接收数据长度不稳定问题

    最近在做一个实时接收数据的项目 xff0c 需要每2ms接收下位机发来的两帧数据 xff0c 算是串口高速接收 在使用的过程中 xff0c 发现串口接收的数据长度不稳定 xff0c 有时长有时短 代码如下 xff1a connect ser
  • git的使用入门

    1 添加个人信息 git config global user name 名字 git config global user email 邮箱 git config global user phone 手机号 查看是否提交 git conf
  • Python-OpenCV之形态学转换

    目标 学习不同的形态学操作 xff0c 例如腐蚀 xff0c 膨胀 xff0c 开运算 xff0c 闭运算等 我们要学习的函数有 xff1a cv2 erode xff0c cv2 dilate xff0c cv2 morphologyEx

随机推荐