标签归档:游戏

RSS feed of 游戏

最后更新于 .

一. 前言

2016年6月17日凌晨5点钟,我们完成了服务器端V3版本的重构,切换的过程十分平滑且没有对线上用户产生任何影响。

这也正式标志着,我们的游戏服务器进入了一个全新的阶段。

我们上一次的重构是在 2014年12月23日,现在看看,时间过的真快啊。

而熟悉我的人应该知道,我特意为上一次重构写过一篇《游戏服务器端架构升级之路》,其中详细的讲述了我们游戏服务器从农业时代跨越到工业时代的历程。

而这次V3版本的重构,我将其定义为第二次工业革命。也许它没有那么的强大和完美,但是他切实的解决了现存的大部分问题。

二. 背景

之前的文章已经说过,V2版本的服务器的几个优点:

  1. 支持服务器代码热更新而不影响外网服务
  2. 架构模式足够简单:push-pull

但是,其简单的架构也存在一些缺点:

  1. 业务模块之间容易互相影响

    比如两个游戏玩法 A 和 B,内部使用的逻辑、存储服务器都完全不同,但是在worker层却是共用的。

    所以一旦玩法A的服务器出现问题导致处理变慢,那么worker就会被堵住,而玩法B也会跟着遭殃。

    同时,即时在一个业务模块内,也存在请求处理优先级的问题,比如拉取牌局记录和跟注,要尽量避免跟注这种核心逻辑受到影响。

  2. 限制了游戏逻辑的实现方式

    V2的多worker的模式,导致worker必须限制为无状态的,因为worker可能处理任何一个请求,而一个请求也可能被分配到任何一个worker上。

    这一点是之前解决服务器热重启的关键,但同时也限制了我们代码逻辑多样性的实现。

    比如我们的游戏桌子数据是存储在redis中,所有人对桌子的写操作可能同时分配到多个worker上,而为了避免写冲突,我们不得不通过redis来实现分布式锁 ...

最后更新于 .

其实打算做游戏内热更新也是几个月之前的事情了,在方案经历了数次变迁之后,最近才终于应用到了外网的bugfix中。
但是就目前数据来看,热更新由于要下载资源,会使新用户的进入门槛变高,所以留存收到了一定影响,基本降低了10个点。
当然,也可能是热更新的功能存在bug。

好了,我们还是进入正题吧!

方案一

最早的时候,我们想用一种类似打patch的方式来更新。
即将lua代码和资源打成一个zip包,而每个zip包只要代码或者资源发生变化,都会有一个自增的小版本号(大版本号为打在apk或者ipa里的版本号)。
不同的zip包之间diff就可以生成一个patch文件,而为了开发的简单,这个patch列表只会将文件路径列出来,之后客户端要去完整的下载新的文件覆盖。

然而这个方案有很多的问题。

  1. 小版本号不好维护 因为代码和资源会不停的修改,而如果人工来维护小版本号,会极其复杂。如果通过机器来维护也是个很麻烦的工程

  2. patch包太多 如果我们将小版本号的patch包先生成好放到服务器上,那么如果我们有100个小版本,就会有非常多 1->100, 2->100, 3->100 ... 这种格式的patch包。 并且如果小版本号继续增长,patch包的增长基本会失控。

  3. 消耗大量流量,速度缓慢 也许有同学会说,不如只有 1->2, 2->3, 3->4 这样的单个小版本之间的升级patch,客户端自己挨个下载就好。

    但是这样客户端如果是个很小的版本号,就不会不停的重复下载,导致迟迟进入不了游戏,并且流量也大量消耗。

综上所述,方案一有太多的弊端。
这也是为什么我们做完了之后迟迟不敢上线的原因 ...

最后更新于 .

这几天的心情非常好,主要原因是我们把服务器端的架构升级到了 2.0,这样最大的一个好处就是:

Server重启完全不会影响外网服务

所以,也是想趁此机会,服务器端整个发展的历程,跟大家分享一下,干货比较多,框架代码也会全部开源:)

 

一. 农业时代

创业最重要的就是一个“快”字,所以最开始的时候,所有的架构都以快速出模型为前提。

而常看我博客的朋友应该知道我对python情有独钟,所以自然的,python成为了我开发服务端框架的语言。

python自带的多线程tcp服务器框架非常简单:ThreadingTCPServer,即每个链接一个线程的模式:

import SocketServer

class RequestHandler(SocketServer.BaseRequestHandler):
    def handle(self):
        f = self.request.makefile('r')

        while True:
            message = f.readline()
            if not message:
                print 'client closed'
                break
            print "message, len: %s, content ...

最后更新于 .

这两天整理电脑里一堆乱七八糟的东西,无意中翻出了本科时和室友一起做的一个小游戏,重温了一下,发现还是蛮有意思的,决定把它写下来,算是一篇开发回顾吧。

这是游戏截图:

1

额,游戏不是原创,而是来源于原来上课时经常玩的三星手机上的一个游戏,后来因为我们太有爱又太无聊了,所以就自己写了一个。

游戏虽然小,但是从框架设计到UI、音效、评分系统,全部都有了,称得上是麻雀虽小五脏俱全。

其实无论从代码上还是最后的作品上来看,这个游戏都没啥值得骄傲的,但是即使过去几年了我和小猪偶尔提到这个作品还是会洋洋得意一番,在我看来,再某种程度上,这几乎算的上是自己做过的最好的一个项目了(当然本人也没多少开发经验),且不说敏捷开发的过程,这是我那时做过的不多的作品里唯一一个彻底贯彻了“前台界面和后台逻辑分离”这一原则的,除了coding之前的简单设计和中途的简单调整之外,我们两人的工作几乎没有交集,我只负责游戏的逻辑,小猪承包了所有的界面工作(最后一个晚上我看着小猪通宵的PS游戏里需要的图片素材,几乎是一个像素一个像素的修改,做美工果然很累啊),直到最后两个模块完美的结合在了一起,那时有一种酣畅淋漓的感觉。所以项目的架构绝对是第一重要的。

下面是源码的下载地址,有兴趣的可以去看一下:http://download.csdn.net/source/2228978