两年多里自己都干了什么?

       2016年7月份毕业,算上实习的几个月时间,工作两年多快三年了,自己都干了什么,回顾自己的职业生涯,大部分的工作都在在从事游戏服务器的开发。虽说有时候加班会很严重,但是熬过来了。但是想想过去的加班大部分的时间不过是在陪别人加班而已,作为一个初入职场的学生,自己解决为题的能力实在有限。

       先说说这段时间里看过的书吧,我觉得作为职场菜鸟,通过看书来稳固自己的基础是很有必要的。c++primer第五版(大学时候基本上看完了,只是回过头看了一下之前没看懂的),你必须知道的222个c++问题,effective c++,深度探索c++对象模型,c++11新标准的并发和多线程编程深度指南,提高c++性能编程技术,Effective.Modern.C++,tcp/ip详解和socket套接字编程(这两本没看完实在太厚),libevent源码详解,stl c++11,算法导论(实在太高深看不下去啊,驾驭不了),Unix环境高级编程,大型网站架构设计原理等等,还有一些关于java和golang的东东。

      工作之余自己搭了一套c++游戏服务器的架子,首先说明并不是从零开始写的,是基于一套比较成熟的框架的基础上改的,只是里面的所用到的东西太过时,并且是单线程的不能充分发挥多核cpu的优势,所以自己动手把整个框架改了一下。

      首先说下老的框架,我猜这套框架应该是一套用来mmo或者rpg的一套东西,基本上是多进程单线程的技术方案(下面提到的服务器基本上是单线程模型)。首先一个网管服务器接受客户端的数据(手写的epoll网络模型,现在应该很少人自己写这种东西了),然后是gameserver,dbserver,sceneserver,logserver等,这几个server都作为客户端连接一个叫做proxyerver的服务器,负责gameserver,dbserver,sceneserver,logserver这些服务器之间相互通信,看起来很简单,但是我觉得你如果能写出这一套东西,并且处理好每个服务器之间的通信,解决开发工程服务器出现的各种个问题,并且能扛得住并发压力,你已经成为高级工程师了。

      接下来说我对这套看起来很老旧但是很实用的东西做了什么(所谓的一招鲜吃遍天,大多数的游戏服务器大同小异都差不多), 首先网络部分,改用libevent简单易用,且跨平台。

     其次是网管服务器gateserver,单线程,线程1:libevent事件循环线程,负责处理libevent事件,包括消息的加密和解密等,派发读写事件,读写客户端上行数据,负责检测是否有需要下发gameserver客户端的数据给客户端,这里说一下,gateserver和gameserver通过两个共享内存管道相互通信,a==>b,b==>a即a写b读,和b写a读,从而加快两者的通信速度,当然这里也可以用socket,如果你的通信量大,共享内存可以提升服务器的消息吞吐量,不过共享内存也限制了gateserver和gameserver进程必须在同一台物理机上。当然这里的通信方式可以有其他的选择,比如socket,虽然传输效率上没有共享内存快,但是没有了必须同物理机部署的限制,不过socket还有另外的问题就是需要处理两个进程之socket断开的问题,在上行和下行数据时,如何保证数据的完整性和正确性。当然还有另外一个更简单的处理方法,就是把两个进程合并为一个进程,但是这和第一个选择没有根本的区别,虽然编程方面相对简单,但是相对于第一种框架的整体扩展性和维护差,比如我们在后期处理gameserver崩溃或者增加其他类型的服务进程的时候,我们可以通过gateserver做很多工作,但是如果gate和其他进程耦合到一起就没有发挥的空间了。

      接下来是gamesever,这里负责百分之90的游戏逻辑处理,首先有一个逻辑线程:线程1负责处理游戏逻辑.线程2:libevent事件循环线程(这里主要负责和proxyerver通信),派发事件(timer事件和io事件)接收和发送proxyserver之间的消息,监听和gateserver的写共享内存管道是否有数据可读(前面已经说过和客户端的通信通过共享内存管道),如果有读数据解包后push到逻辑线程,处理逻辑。线程3 计算线程:如果有复杂的逻辑计算可以先push到计算线程计算完成后,然后再push回逻辑线程处理逻辑,减轻逻辑线程的负载

   这里说下逻辑线程,可能有人会说为什么不把逻辑线程线程一个线程池多线程处理逻辑,我并不否认这样做会增加服务器的处理能力,对于一些逻辑简单,玩家之间没有数据共享或者共享少的情境下这样处理完全可以,但是对于有大量数据共享的场景,并且玩家可以离线操作另外一个玩家的数据的情况下,我们需要大量的精力和工作来保证数据的一致性。最粗暴的就是加锁,但是大量的加锁会极大的降低服务器的处理速度。还有一个就是开发过程中可能会出现很多奇怪的问题,都是由于多线程处理逻辑不当造成的。所以逻辑线程采用单线程还是线程池视情况而定吧。

  其次是dbserver,logserver等这些主要处理来自proxyserver转发而来的数据,基本上没有复杂的设计,都是一个libevent事件线程处理所有的逻辑。

  架构图:

  

      当然目前只是一个基本的架构,很多细节仍在完善,比如说意外宕机事故处理,如果是滚服式的游戏类型,到这里工作基本上差不多完成了。但是如果要做全球同服,这样肯定是不行的,必须通过负载均衡或者分布式来支撑,这也是接下来我主要研究和完善的内容。另外闲暇之余会了解下go和java。

### 回答1: JVM内存模型是Java虚拟机的内存管理模型,它用于管理Java应用程序的内存使用。JVM内存模型包括以下几个区: 1. 程序计数器:保存了当前线程执行的字节码的行号指示器,它是一个较小的内存区域,不会对Java对象造成影响。 2. 虚拟机栈:保存了Java方法执行的内部状态,每个方法执行的时候都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。 3. 本地方法栈:与虚拟机栈类似,但专门用于执行本地(Native)方法。 4. 堆:是Java虚拟机所管理的最大一块内存区域,用于存放对象实例。所有对象实例以及数组都在堆上分配内存。 5. 方法区:存储了类信息、常量、静态变量、即时编译器编译后的代码等数据。 JVM通过这些内存区域管理Java应用程序的内存,保证程序的正常运行。 ### 回答2: JVM(Java虚拟机)内存模型是用来管理Java程序运行时所需的内存的。JVM内存模型主要由以下五个区域组成,分别是:堆、方法区(也称为永久代)、虚拟机栈、本地方法栈和程序计数器。 1. 堆(Heap):堆是JVM内存中最大的一块区域,被用来存储对象实例和数组。堆被所有线程共享,而且在JVM启动时就创建了。堆被进一步划分为新生代和老年代。新生代包括Eden区和两个Survivor区(From和To区),它们主要用于存储新创建的对象。老年代用于存储长期存活的对象。 2. 方法区(Method Area):方法区用来存储类的元数据信息,包括类的结构、常量、静态变量、即时编译器编译后的代码等。另外,方法区还包含一个常量池,用于存储类的常量。 3. 虚拟机栈(VM Stack):虚拟机栈用于存储每个线程的方法调用和局部变量信息。每个线程在执行方法时都会在虚拟机栈中创建一个栈帧,栈帧包含了方法局部变量表、操作数栈、动态链接、方法出口等信息。 4. 本地方法栈(Native Method Stack):本地方法栈类似于虚拟机栈,但是它是为执行本地(即非Java)方法而设计的。它的功能和虚拟机栈类似。 5. 程序计数器(Program Counter):程序计数器是每个线程私有的,用于存储当前正在执行的指令地址。在任意时刻,一个线程都只能执行一个方法,程序计数器记录了当前线程执行的字节码指令位置,当线程被中断或者被调度时,可以恢复到正确的执行位置。 这些内存区域在JVM内存模型中各自承担着不同的职责,通过合理的调配和管理,可以提高Java程序的性能和安全性。 ### 回答3: JVM(Java虚拟机)内存由多个不同的区域组成,用于存储不同类型的数据。主要的JVM内存区域包括: 1. 程序计数器(Program Counter):用于记录当前线程执行的字节码指令的地址。在多线程环境下,每个线程都有自己的程序计数器。 2. Java栈(Java Stack):用于存储局部变量、方法参数、操作数栈和方法调用的信息。每个方法在执行时都会创建一个栈帧,栈帧包含了方法的局部变量和操作数栈信息。 3. 本地方法栈(Native Method Stack):用于存储执行本地方法(非Java代码实现的方法)的信息。 4. 堆(Heap):用于存储Java对象实例和数组。堆是JVM内存中最大的一块区域,可以被所有线程共享。在堆中,对象实例的分配和回收由垃圾回收器负责。 5. 方法区(Method Area):用于存储JVM加载的类信息、常量、静态变量、方法字节码等。方法区也被称为永久代(Permanent Generation),尽管在Java 8中,永久代已经被元空间(Metaspace)取代。 6. 运行时常量池(Runtime Constant Pool):是方法区的一部分,用于存储编译时生成的字面量和符号引用。常量池中的内容包括类和接口的全限定名、字段和方法的名称和描述符、字符串常量等。运行时常量池是每个类或接口的常量池表的运行时表示形式。 除了以上主要的内存区域外,还有一些其他的内存区域,比如直接内存(Direct Memory),用于存储通过NIO类库分配的字节缓冲区。直接内存并不是JVM中的一部分,但是它可以被JVM管理。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值