我玩过的游戏

在游戏行业也算是十多年了,奇怪的是,其实很久以来,对游戏都提不起太大兴致。很少能有游戏让我随时都想着去玩。这点上我是很惭愧的,所以也一直不好意思提。

身处游戏行业,经常会被人问到的,当然就是“最近玩什么”“喜欢什么类型的游戏”。

所以今天我就来好好盘盘这个问题。

最早最早接触游戏,应该就是在邻居哥哥家,那时候他刚买了一台电脑,应该是在02年吧。

更准确的说应该是最早接触的PC游戏。实际上好像家里很早就不知道从哪买过一个掌机,那种几百合一的,里面有俄罗斯方块、赛车、打砖块什么的那种。小学二年级也收到过奶奶拿来的姐姐不用的“金字塔学习机”,也就是个国产FC。自带的“学习卡“里唯一的一个游戏是坦克大战。后来我也搞到过几盘游戏盘,玩了很久的空中魂斗罗、摩托车、马戏团什么的。那时候最想要的就是能接在彩色电视机上看看游戏的颜色哈哈。初代马里奥应该也是有的,很小的时候在姐姐家似乎玩过赤色要塞,那种大地图的感受着实惊到我了,不过后来没弄到过盘,也就再也没玩过。

言归正传,还是聊聊在隔壁邻居哥哥家玩的PC游戏吧。最早他买到的游戏是《沙丘2000》和《盟军敢死队》。没错,就是近几年很火的电影沙丘的游戏版本。当时对这个游戏唯一的印象就是胖机器人和瘦机器人了,怎么玩也完全不记得了,只记得似乎是个RTS游戏。后来他不知哪里弄来了帝国时代2。这是我们那段时间最喜欢的游戏。经典操作是开自定义地图,然后放一堆百夫长和大象,看谁打得过谁。我们那时候把百夫长叫做”大丈夫“,因为确实很强。

再后来就是我爸不知道从哪里搞来一套别人不要的电脑,是台联想品牌机,赛扬2CPU,180nm制程,128M SD内存,i815芯片组,20G迈拓硬盘。记得那时候我好像比较沉迷金山画王,后来渐渐开始搞倒了一些游戏。

有几个游戏是我妈妈请同事叔叔来装的,叔叔姓左,她女儿叫左佑,很有趣的名字,我似乎没有见过她的印象,不过好像因为我妈把什么东西拿给她吃了我还不太开心,所以印象不好。小朋友就是会有这样奇奇怪怪的心理,扯远了。

从隔壁哥哥家弄来的游戏是帝国时代2、模拟人生。同事叔叔装了红警、星际争霸。不知道为什么,那个年代我能得到的RTS游戏就特别多,不过对我来说实在有点过于复杂了,我基本只能打打红警。

平时玩得最多的还是太阁立志传2和模拟人生。这应该也是我小学阶段最喜欢的两款游戏了。

好像从那时候我就体现出对玩游戏毫无天赋。我甚至很长时间都不认为太阁立志传2是个能玩的游戏,花了很久才搞明白是怎么玩的。再后来,我还从同学那里借来了太阁立志传4,这个也玩了非常久的时间。

其他印象深刻的游戏,就是剑侠情缘了,女主摔下悬崖的剧情是我中午偷偷玩电脑看到的,导致我后面很久都无心学习,非常郁闷。后面看到她其实没事,又开心了起来。

那段时间还玩了”最初幻想“,没错,这是台湾做的一款仿制游戏。这充分也证明了我在玩游戏方面毫无天赋。我前几个月都被卡在了新手村,根本不知道有段剧情是要往回走才会触发。这是在一个同学看到我有这个盘,借给他玩以后他告诉我的。记得后来确实往后玩了挺多内容,然后就学会了用金山游侠。

仙剑1是跟妈妈去学校机房,玩了两天打完的。也许当时用软盘拷贝回家再打完的,不是很确定了。

差不多的阶段,在过年的时候,跟着哥哥姐姐上网吧,接触了传奇和泡泡堂。传奇我是没玩懂,泡泡堂倒是很喜欢。

在二姑家好像玩了一段时间的”洛奇“,也是没怎么玩懂,瞎玩哈哈。

说到这不得不提学校机房常备,”小朋友齐打交“了,我们那时候叫做热血格斗。确实风靡了一阵,机房另一个常备游戏,则是暴力摩托。当然还有我的拿手好戏,Excel 2000自带的菜单赛车,以及Flash自带的彩蛋折射小游戏。

这些似乎就是小学阶段的游戏经历了。

解决网易云音乐Windows客户端音质差的一个方式

我几乎不在电脑上听歌,主要是因为Windows版本的网易云音乐不知道为何,我总觉得音质特别差,不管用什么耳机听,都是一团糊。不管开会员用高音质,还是选Wasapi换输出,甚至外接声卡,都没有任何改变。

同样的音乐,用foobar就完全不一样,但是习惯了在线听歌了,本地下载肯定没法接受。

说一下foobar的环境,输出是走ASIO用外接DSP,而网易云完全不支持ASIO,那会不会是这个原因呢?

然而不支持就是不支持,难道有什么办法可以解决吗?

还真给我找到了一个。

VB-Audio Hi-Fi Cable
https://vb-audio.com/Cable/

这个软件原理很简单,生成了一个虚拟设备,可以将输出到这个设备里的音频传输到ASIO设备上。

具体实现,只要安装驱动,打开ASIO Bridge软件,输出选为你需要的ASIO设备(一般为独立声卡)。

然后在网易云的播放选项里,输出选择WaveOut: Hi-Fi Cable Input。

现在你可以享受ASIO的输出了。

当然我也怀疑过,明明还是靠WaveOut输出,这样“只换末端一截线”真的有意义吗?

我只能说,我听上去确实还是很明显的,至少网易云Windows客户端的声音现在能听了。

这也算是困扰了我很多年的问题,值得记录一下。

把手绑在背后没有说明书拼高达

解决问题的第一步,也是最困难的一步就是发现问题。

所以这一篇,就是一个发现问题,然后确认,再尝试去解决的一个记录。

有一句话,叫做“我懂得很多道理,却依然过不好这一生。”

最近讲了太多关于“讲道理”这个事情,几乎快要替代“做正确的事情”在我心中的标杆地位了。但是最近的一些事情和思考,另外重新开始考虑,然后很显然的发现,“讲道理”并不一定是“正确的事”,所以“讲道理”其实只是一个解决问题的方法,并不能成为一个信条和根本驱动,在这个事情上,“讲道理”这件事情,太具体了。

想一想为什么会发生这样的事情呢,也许和这段时间的管理培训相关吧,因为在思考这样的问题,急于想找出一种方式向他人表达自己的观念,并且自认为找到了(“所谓讲道理的事情”),而且还觉得很有效,于是不由自主,不知道什么时候开始,自己不讲到底得开始强调“讲道理”了,在向别人一遍遍重复的时候,也对自己一遍遍重复。然后发生的事情,戈培尔已经告诉大家了。

现实世界中,发现了“万物理论”这种好事情是不会发生的,如果感觉发生了,可能就是错误的开始。

当然,一个你自己都解释不清楚的“万物理论”倒是没问题,比如我的“做正确的事情”。一个混沌的理论也就无所谓“遵守”。

说回具体的事情。

一直以来的行事方式都很简单粗暴:排除限制,解决问题。大部分的事情的限制其实都来自于自己,所以只要你“不要脸”,很多问题的解决其实都很容易,实际上也不需要什么特别的技能。所谓光脚不怕穿鞋的。

解除限制的过程,也是个拼命思考的过程。现实中的限制,往往都不那么显而易见,打破常规是必须的。这样的拼命思考,又带来一个问题:想太多。这个副作用其实不大,用“小心谨慎,深思熟虑”的说法就可以很轻易的说服自己。“至少想多比没考虑到要好嘛”。而问题的复杂和混沌,实际上也必须要依靠更加复杂和多层的思考,才能所谓“抓住本质”。“抓住本质”,变换问题,寻找真正需要解决的问题,可以说是最简单有效的方法了。

毕竟,只要问题在不断解决,其他的都不是事。甚至战略上的懒惰都能轻易的被战术上的成功掩盖。

并且,按照这个简单的逻辑,实际上也能发挥极大的杠杆率,让你成为环境中最能解决问题的那一个。习惯于自己解决问题。也确实的难以依赖他人。

追求正确性+讲道理带来了一个问题,就是难以让别人接受观点与帮助别人成长。换句话说,不好带人。这是一个我长期发现,但是难以接受以至于有点逃避的问题,事实上说,我其实不擅长带人,或者说是确实没有成功帮助别人成长。之前我也给自己提出了很多理论解释这个问题。从早期的寻找各种方法,到后期的觉得“就是不行”。但是实际上现在看来,原因很简单,“道理”这个东西,就是屁股决定大脑的,每个层级上需要解决的问题不一样,所以讲的道理也实际上是不一样甚至是截然不同的。而我的追求正确性,一个是让我经常没法花时间去讲道理(需要尽快解决问题),二是,讲出来的道理都过于“正确”,可能对特定对象来说就反而不是最佳的了。

这些问题,在早期其实并不会有太大的影响,而且对实际的发展很有帮助。甚至我依然觉得能有今天,之前的方法和方向还是对的。

(此时此刻,想太多的问题依然影响着我,每想到要写一段,就会想写10个背景知识说明为什么会产生这样的情况,以及为什么在当时是正确的,然后再说明10种情况下的变体,然后思绪就飘忽到天国去了)

但是到了现在,我必须要承认,在实际事情上的能力,我已经不如团队了,最基本的事情,原来可能我写的代码是最不会出bug的,最近发现,写的所有的地方,过段时间都能看到被修复的commit。而从团队的立场上,是不能把我考虑进项目流程中的。我对于团队就像是个网上认识的对项目很感兴趣,想要义务帮忙的热心网友。对于这种情况,我的观点一直很明确——再强都不能要,或者必须要有非常明确的隔离,并且不能有任何预期。事实上,团队也是这样对我的(当然正确,当然,也令人沮丧)。这样,对我来说最困难的情况就发生了——

我发现我不能靠参与项目来获取信息,让自己进步,但是我现在所在的职位要求我应该有巨量的信息并且做出决策。突然就死循环了。

意识到这个问题的时候,我的第一反应是这不讲道理。我能力不足我承认,但是我一直都很努力的从项目中学习,希望经历跟进项目的过程,能够成长。但是根据上述逻辑,其实我被禁止了这样做,这相当于要求我成为一个架构师,却不许自己写一行代码?甚至看别人写都得小心谨慎,因为很容易围观的时候一句话,造成未知的影响。

最绝望的问题在于,实际上自己是没有得选的,最终必须要解决问题。

真正意识到这个问题的沮丧感还是挺打击人的,首先从道理推断这些都是对的,那么我之前的行为就是个巨大的用“战术上的勤奋掩盖战略上的懒惰”。而且我过去一直以为自己只是用这种方式来度过一下低谷期,现在想来,其实我根本就没有在自己的职位上做正确的事情,我只是纠正了一些显而易见的错误,然后做了一些显而易见正确的决策,然后就安心的继续把自己当成一个优秀的程序员了。

想清楚道理,认错并不困难,困难的是然后怎么解决。虽然事情依然困难,但是已经知道了问题,至少就有很多方向可以去尝试了,首先我第一反应就是觉得可以去问人,第二天,我去找了Kiro。

Kiro那天很忙,下午开了很长的会后还跟我聊了很久,真的是很感谢,结论上说,我感觉很有帮助。

Kiro的观点是,我的根本目的是为了让事情做成,那么项目只是公司发展的一个部分,并且帮助项目做成的方式不一定是要靠直接影响项目,甚至直接写代码。眼界开阔一些,必须要承认有些事情就是没法控制的,也不可能控制所有事情。就算之前的经历让我有“事情最终都还是要靠自己解决的”,还是依然要再试一次。

我之前的观点在于,我直接影响项目,是最直接有效来确保达成目标的方法,但是事实上却是不一定是最好的方法,影响总会分积极和消极。这段时间的很多纠结都在于,我想确认到底这个影响是积极还是消极,以及没法说服自己,真的不这样做。有可能我回家躺着是对项目最好的方式,但是我又如何才能让自己确认真的是这样呢?

所以到底我还是没有确认这一点,但是Kiro的话让我发现了其实却是我还是有很多可以做的事情,可能过去是我不喜欢的,但是跟现在这种纠结的心情相比,那我就宁愿去做这些事情了。既然我事实上对现在的团队有着确实的信任,那何必想太多,一定要把道理讲到“100%”呢。

虽然我懂得很多道理,但是道理之上还有meta-道理,一件事情在这个角度符合自己的道理,在另一个角度可能就违反了。其实道理对自己来说,更像是一个让自己心安的借口。所以“讲道理”这件事情,还是应该让它去适合自己的地方——用于统一集体的文化价值——上去发展吧,束缚自己,就成了真的“不讲道理”了。

有着细腻的感情描写的真实系动画

这个方向的起因应该还是《春物》吧,也不记得是具体什么时候,我给自己喜欢的番总结了一个特征,叫做

“有细腻的感情描写”

好像些微记得是为了跟诸谦解释?

最近在找此类番的时候,看到一个说法,我一看就知道对了。

“真实系”

没有什么大起大落大喜大悲,就是一天天发生的事情,好像自己能多经历了几种人生一样。这样最好了。

所以想写这么一篇,List 一下我目前看过的这个风格的片子。如果发现了新的,也可以随时补充。

以下还是分几个组吧。主要还是因为有些动画也不能完全说是日常,真实,但是我感觉也很细腻,所以私心想放进去。

顺序以自己的追番时间先后为准。

绝对符合

我的青春恋爱物语果然有问题

多田君不恋爱

川柳少女

月色真美

Just Because

玉子市场(玉子爱情故事)

这几部,就是青春校园,一天又一天,以至于,你要说让我说说这几部讲了个什么故事,就是难为我胖虎了。

掺杂了点奇怪的东西

冰菓(推理)

人渣的本愿(额……其实讲道理确实是青春校园,我只是没脸放在上一组wwwww)

比宇宙更远的地方(倒不是多了什么……而是这番根本没有恋爱啊!但是小南极赛高!)

少女编号(同上)

青春猪头少年不会梦到兔女郎学姐(青春期症候群……这算哪种?)

齐木楠雄的灾难(这就是非日常的日常,相对《日常》其实说的是非日常)

女高中生的虚度日常(校园不恋爱)

喜欢本大爷的就你一个(看看前几集就好)

 

 

钉钉的提示音太TM吵了

做梦也没想到,我也有在公司推行钉钉的一天……

主要的点还是,单纯的软件设计上看,很多点还是做得比企业微信好的……企业微信的槽我自己用了两天都已经吐不完了。

另外,能够有效区分工作和生活,这点上还是很能减轻心智负担的。之前每次想找一个人,都得考虑我们一般是用微信还是QQ,想查找一段记录的时候,也得考虑一下是在哪儿聊的。

最后只有一个问题了

钉钉的提示音实在是太!吵!了!

这个吵,一方面是波形本身的增益估计设得比较高,另一方面是估计是有意设置的令人不适,这样能有效注意。

今天实在是忍不了了,直接开AU给改了,降低了10db的响度,并且把起音删除了。

试了一下,感觉好多了。

音频文件在钉钉的安装目录的这个位置:

DingDing\main\current\uiresources\new\common\sound

message

欢迎下载替换: )

2020

在公开的地方写作,就算没什么人(可能根本就没人)看,和自己想表达一些东西,还是不太一样,有些话,自己想想可以,写出来,就不知道会发生什么了。

总之,在半年多之后,总归还是有了写新的一篇的想法。

首先道歉(如果真的竟然有读者的话),装修的话题我可能是暂时不会写了……在新的办公室里也已经工作了一年多,总的来说还是满意的。

2020,看上去很像是个充满赛博朋克感的未来年份,却被踏踏实实地写在日期的栏位中。总归,时间还是会过去。

在给自己做了多年的思想建设后,突然地,有种人到中年的感觉。也许是因为《春物》最后一卷的发售,令人察觉青春真的结束了吧。本来很担心春物的结局会不会崩,但是看到的那一刻就知道,崩不了了。“果然还是他们呀”,发出这样的感叹,然后开心得看着他们的结局,没有那样的不舍,也没有过多的遗憾,真的很完美啊。一部恋爱喜剧,可能只有最后一本的最后三分之一才算谈了恋爱,甚至连手都没牵过,却让我觉得是最喜欢的作品。也许真的果然有问题吧,我说自己(笑)

这个时候写总结,非常有强行的感觉,明明事情才做了一半,却只是因为时间到了,“被迫”。好吧,还是说一说好了。

如果说18年的主要成果是让每个岗位都有人了,那么19年的主要成果就是让团队不再有我过于纠结的人了吧。现在来说,我是真的对现在的团队非常喜欢和敬佩,他们能做到太多我自己做不到的事情。能实现这件事情,回想一下,简直要哭出来。

这个月开始,应该陆续还会有几个能解决问题的人加入,希望在上半年,可以让基本的开发问题,不再令人纠结。

接近去年底的时候,通过对一位前辈的拜访,让我对项目要做的事情本身有了清晰的认知和计划,转化留存付费,谁都知道,但是真的就是这个。

真的去年底的时候(12月18~23日)去马来西亚首都吉隆坡逛了一圈。马来西亚是我们目前测试阶段的主要买量地区。之前真的是完全没有概念,这一趟下来,大体上还有有了基本的认知。比较没有想到的意外收获,来自于在宾馆看的YouTube。也是非常神奇,虽然说在国内要想看也是可以看到,但是真的不太理解到底看个啥。对于平台的量级也是比较想当然。由此受到的启发,我在考虑做一些不一样的事情,总之多做一些尝试吧。用事实说话,好过纠结和空想。

虽然说目前还是不太能安心做事,纠结的点也有点多。不过感觉2月份,当预期的援助力量全部到齐后,应该会有所缓解。现在的时间点,感觉真的不是个好的总结时间,但是姑且算是个记录吧。

期待下一次打开页面的心情。

关于装修

这一篇突然开启了一个神奇的话题。

当然,不是因为我突然中大奖买了房所以准备装修,只是突然被要求搬离从创业开始就一直待着的心动办公楼,于是就需要自己解决办公场地问题了。

相对于家装,公装接触过的人就少很多了, 但是对于大多数早期创业者来说,又是跨不过去的坎。向我们这种,这么多年都靠蹭别人的完善环境,突然一下需要自己来,对于需求和预算的把控就很容易出现大的偏差。所以突然就很想吧这个过程记录一下,也算给遇到同样问题的小伙伴一些参考。

因为这个问题实在头疼(如果不算项目本身的话,甚至已经可以算这几年来处理的最复杂的综合性问题了)。从4月以来服务器这边就基本没有耗费太多精力,主要就是加入了一下cluster_client的定期断线重连机制,这样也可以解决其他节点依赖cluster_manager节点先启动的问题。

项目管理

一开始要确定这件事情,我的第一反应还挺开心的,本来独立确实是有独立的好处,而且装修也勉强算是个小的建筑工程嘛,本来就是我一直希望尝试一下学习的事情,可以从工程界的鼻祖——建筑工程,推知一些软件工程方面的参考。项目目标明确,也不是很大,干系人也少,项目发起人又是自己,本来的确觉得是个轻松有趣的项目。(后来……

在Teambition上面开了一个项目,名称简单粗暴就叫做“新场地”,只设了一个任务组,分成房源、交房、方案、施工、搬迁五个列表,分布进行。因为这件事情是突然加出来的,打乱了本来的规划(年底项目上线之后再考虑搬迁),所以并不希望(也确实没有多余的精力)在这件事情上面付出过多。总体是按照尽量不改变现有的习惯和尽量让风险最低的原则进行规划的。时间方面,心动可以在现有场地无法使用之后为我们提供1~2个月的过渡场地,也就是说,从项目开始到可以入驻,总共大概是3个月的时间。那么就抓紧开始吧。

找房源

第一反应肯定还是想继续呆在现在的园区里,毕竟很习惯了嘛,换一个园区也不知道换到哪里,范围太广了。面积的话,之前我尝试联系一家共享办公的时候,大概做过一个规划,预期到明年的时候可能要达到40人,需要大约500平米的场地(包括一个会议室和财务室)。在稍早一些的时候,在樊少的帮助下,联系了园区业主看了几个场地,都没有非常满意。所以一开始我想看看其他的场地,找了一个做中介的朋友,开始帮我推了很多场地,一个个去看了。各有各的问题,还是没有看到非常满意的。回来的时候向园区业主又确认了一下,之前看的那几间还有没有了,结果发现最近又有了一间新空出来的,但是面积只有350平米,比预期小很多、虽然觉得可能不太行,但是之前看的场地让我有点觉得500平米是不是过于大了,赵宁也说她之前的公司,500平米的场地是可以排70多个工位的,于是死马当活马医,反正先去看看再说。

一进去第一印象还不错,装修比较新,感觉也挺大,一层感觉都是一些咨询位,还有一个淋浴间(我一直希望的,虽然知道使用频率机会为0),肉眼可见的面积已经不小了。走上二楼,有一个玻璃隔离的空间,里面有一个封闭阳台,以及一大块类似培训室的空间。玻璃房感觉可以作为会议室或者财务室,培训室面积不小,作为工位几乎已经可以安排下我们现在的所有人了。正看着,业主催促我再去三楼看看,这我才注意到玻璃空间里还有一个楼梯间,正是通往三楼的楼梯所在。本来两层的面积已经基本可以接受了,发现还有一层实在令人意外,我不禁向业主确认:这真的是350平米吗……

三楼的结构有些奇怪,两面都是满墙的窗户,可惜并不能打开。整个三楼被中间一堵墙分成了两件,墙的中间有一扇门,奇怪的是,门开在离地大约1米的位置,需要通过5级台阶上下。业主解释说,这个和之前带我看过的一间结构类似,整个三层实际上是阁楼,所以面积是不算在租赁价格中的,我们看到的结构实际上是一道梁,如果想到达另一边,必须要跨越这道近一米高的梁,所以才有了这样奇怪的结构。

回来以后我根据业主给的资料,找了些软件重新绘制了正确比例的图,简单的排了一下座位确定面积是否足够使用。虽然从图上看其实使用面积只有大概200平米(刷新了我对于面积的认知),但是面积确实是够的。总之,最终经过全面考虑,我们确定了想租下这一间,于是就开始准备谈价格、合同等等,同期开始准备起装修的事情。

确定装修承包商

说到装修我真的是完全没有一点概念,需要哪些需要花多少钱都没有任何参考,这种事情很明显在网上也是查不到的,就如同之前开发PS4的时候的烦恼,因为会接触这块的人实在太少了,公开渠道就很难指望有人分享一些经验。比较靠谱的方式是在身边找寻。我对于现在的环境当然还是一直比较满意的,所以第一反应当然就是找我们现在所在场地的装修承包商。通过介绍,联系到装修老板,老板也很快就带队上门来测量讨论方案了。与此同时,租赁的合同也基本确认了,看起来周末就可以开始动工了。

一切的顺利在我第一次收到报价方案的时候戛然而止,看着报价上面完全超乎预期的数字我真的差点没被吓死,单看每一项,价格都非常有槽点,虽然大部分我也不了解,但是总会觉得真的至于这么贵吗。跟老板交流,明确表示这个价格要远超我们之前沟通的时候确定的不超过每平米1000元的平均价,对方给出的解释是,因为我们的装修都是需要在夜间的(噪音施工),所以人工费要翻倍。我当然哪有这么多噪音施工,但是如果要我直接跟他怼,很明显我这边处于信息弱势。并且也过于消耗自己的精力。这时我才意识到,我现在做的事情,可能并不能通过一直以来习惯的基于信任的做事方式解决。这也是我在这件事情上面第一次感到厌烦。

我暂时中断了和这家装修老板具体的方案讨论,也放弃了从周末就开始开工的计划,开始乘着周末找其他的供应商。一家是现在住的地方楼下的公司,开了很多年了,看上去业务还挺繁忙。另一家是尝试联系朋友帮忙介绍了一家。楼下的这家明显是做家装为主的,朋友介绍的这家自称是只做公装。楼下这家这个服务挺不错,感觉设计师也很积极,不过不管说什么,都是回答没问题可以做,令人不免担忧靠谱度。相对来说,朋友介绍的这家,聊得挺开心的,在公装方面的专业度也很明显,主动提出了很多我没直接说出来的需求。对应的方案上对比也很明显,楼下这家的方案各种骚操作,竟然还企图给一楼制造段差,进行所谓功能分区,一听就很家装方案。办公室一定要把桌子斜着放,非常不明所以。之前他说的一些可以做的方案,也直接被在场的空调供应商打脸。朋友介绍的这家的方案就比较办公,但是可惜他对二楼的改动实在太大了,并且我觉得按照这样的方式,可能也不够好用。这两家共同存在的最致命的问题在于——他们都把设计图画错了。被我寄予厚望的朋友介绍的这家错得甚至非常离谱。相对而言,我们一开始找的贵得一塌糊涂的这家,至少图是画得最准的。在这种我个人觉得真是最最最基础的问题上面出错,实在是令人很难接受。不过,经过跟两边的沟通,我对于项目的规模和预算以及方案都有了更准确的认知。一般即使是完全从白胚的公装,也就在800~1000这个价位(不包括空调家具设备,但是包括弱电布线)。我也在Teambition上面整理出了一份基本需求。与此同时,我从公司内自己装修过房子的同事那边获得了不少信息。几天没有回复后,贵得一塌糊涂的这家老板可能也有点急了,又来在找我,意思说是,本来不清楚我们需求只是简单装修一下,所以做了很多的额外设计,并且答应回去重新出一份报价。

时间有限,如果再去找新的供应商,说实话这是一件没有底的事情,毕竟之前没有经历过的话,很难找到一个可以完全信任的合作方。既然怎么搞都无法按照完全信任的方式合作,那就只好被迫完全基于非信任合作了。虽然我实在非常不愿意这样,效率也非常低。但是在初次的外部合作中,也许这也是无法避免的吧。

我开始考虑找一个监理帮忙处理过程验收了,说白了就是有一个全程顾问可以帮我补充所有信息。碰巧了,一个同事的一个同学,之前也一直在向他咨询一些细节问题的,正好就是做监理的。那不废话了,直接约他见面聊聊。我带了报价去见他,他也带了他们这边的设计师过来,我们一项项对了报价,因为是专业做这方面,所以价格是很清楚的。我们把所有不合理的价格都扣除(保留正常的利润),得到了一个我们可以接受的最高价格,在此基础上面再降低一些作为谈判的余地。有了这次的沟通,我心里也就有底了。

回去的路上,刚出地铁站,装修老板就打电话过来,我也直截了当地跟他说:“我报个价格给你,你看能做伐?”经过一番确认,我也是考虑为了避免未来的麻烦和加价可能,稍微放宽了一些底价,最终达成了双方都满意的结果。从结果上看,真的大概是最开始的价格砍一半,放下电话,算是放下心来,这个比较大的问题终于确定好了,但是也不禁很无语,单单是确认装修供应商这个最初的问题,就需要花费这么多精力获取信息,这样基本断绝了我指望自己在不去过多了解装修的专业信息的情况下,解决这一问题的奢望了。果然还是,“自己解决不了的问题,也不可能靠他人解决”。

(目前装修还是在早期的进度,下一篇准备说说空调和弱电)

 

 

游戏服务器的集群问题

(这篇可能希望可以长期更新,记录一下这个问题的解决过程,最终可以产生一个方案)

遗留的两个问题

目前游戏服务器框架是使用的Skynet,之前的所有开发设计都是基于单机情况下的,在配合了Gitlab-CI之后,已经可以非常爽快的使用了。代码合并进master分支之后,会被pipeline自动构建并部署到阿里云的测试服务器上。在年底的时候,因为终于有了一位正式的服务器程序( 雷迪 )入职,在做完框架交接之后,基本就是他直接和产品那边配合开发逻辑了,我也把精力放在了其他方面。

在当时我这边暂时脱离服务器开发的时候,实际上还有两个点不放心,或者说在正式上线前必须解决。一个是数据库,一个是集群。

目前的数据库连接方案是我基于Redis和MySQL,写了一层薄封装,称为Unistore。这层封装本质是是给MySQL实现了一套Redis接口,这样一来,Redis就完全变成了一个缓存,数据实际上都是存在MySQL里面的。做这件事主要还是上一篇日志描述的事情给我带来很大的鸭梨,觉得数据这种东西还是小心点好。不过因为实现得比较粗暴,写入的时候是直接往Redis和MySQL里同时阻塞写入,这样一来,MySQL的写入是大概率撑不住的。这一块我跟雷迪聊了想法,在年前的阶段他尝试了一下改进,目前应该已经是在使用新的方案了,这个下周抽空去找他聊下,作为评审和确定。

至于集群,虽然我很赞同云风的建议,如果靠单机加核数和内存就能解决的问题,是没有必要上集群的。在年前我也对现有的单机部门做了一些压测,情况总体看来还是很不错的,CPU和内存基本压力没有那么大,也很明显只要往上加,性能是可以对应堆上去的。遇到稍微麻烦的问题在于并发连接数,我们的连接用的是TCP,所以用户数和并发连接数成正比,这就是著名的C10K问题了,虽然说,目前应该C10K问题依旧被研究得比较清楚了,但是对于我这样的运维萌新来说还是挺一头雾水的,在研究了半天的Linux kernel参数之后,应该勉强是在两台PC的轰击之下保持了10000+的连接(使用ss -s查看),但是离预期的目标来说还是差挺大的,并且总归是要为未来的拓展做好准备,这样集群方案就是绕不开的问题了。

Docker 与 Kubernetes

最近一段时间,林峰的平台那边因为基本的需求都完成得差不多了,所以开始研究了一下Docker。说来惭愧,我一直觉得Docker应该是很确定的方向,但是几次尝试,都看得云里雾里。Docker本身还是挺好理解的,但是一涉及到实际生产方案,资料就十分匮乏,最终唯一的用途就是在Mac mini上面起了一个Container取代原本原生部署的Unity cache server,这种无状态缓存用Docker还是很爽的。这次林峰的成果大大超出我的预期,在本地使用Minikube进行尝试后,在内网服务器部署了一个IBM cloud private集群,算是对kubernetes的使用有了一个大概的了解,我看差不多可以用了,就开始怂恿他开始往生产环境上面试,于是在阿里云上面尝试了一番容器服务。

阿里云的容器服务Kubernetes版总共有四种,Kubernetes、Kubernetes托管版,多可用区Kubernetes、Serverless Kubernetes。Kubernets和多可用区Kubernetes基本一样,最正常的方案,就是用至少3台ECS作为Master节点,然后加入Worker。托管版就是不需要自己买Master,只需要配置Worker。而Serverless Kubernetes就更厉害啦,连Worker都不用买,直接也被托管了。我们兴趣最大也最先尝试的就是Serverless Kubernetes,完全无视底层虚拟机,完全面向容器,多么令人开心的方案。结果,试了半天,helloworld都跑不通,直接报错无法拉取镜像。无奈只能工单咨询,结果答曰:Serverless Kubernetes的Worker没有公网访问权限,所以无法访问 Docker hub……这我可是头一回听说,我买台云服务器还有不能上网的吗?我又不需要公网访问……仔细研究了一番才明白,VPC还真不能上网,之前我买的几台可以上网是因为我分配了公网IP,如果只是内网机的话,不仅仅是外面访问不进来,里面也访问不出去。这下开心了,Serverless Kubernetes的Worker又不是我的,我也无权分配公网IP,要想上网只能买个NAT服务,价格嘛,12块钱一天……我说就为了拉个镜像至于么,于是开始找寻方法,找了半天还真给我找到了,原来只需要配置一下路由表,把0.0.0.0/0的下一跳指向一台可以联网的ECS,然后在这台ECS上开启ipv4 redirect转发即可,啊,第一次感受到了SNI的强大。配置好之后终于可以拉取镜像部署了。经过一番试用,最终还是放弃了,Serverless Kubernetes的运行本质上还是依赖了弹性容器实例 ECI,但是不知道为什么,阿里云设定每个pod至少分配2核4G内存,这对我们现在的测试实在是太不友好啦(穷),再考虑到方案强依赖云服务商的特定服务也是我一直很不喜欢的,于是出门右转开始尝试Kubernetes托管版。中途解决了各种奇奇怪怪的问题,最终效果非常令人满意,搭配上完整的弹性伸缩服务,现在整个集群都可以根据负载自动伸缩,负载高了,自动加入一台新的ECS作为节点,而ECS我也发现了抢占式实例这个性价比神器,只要不限制最高价格,也不用担心会被回收,平均只需要正常按量计费的1/6价格,目前是用了两台2核8G的ECS测试,每小时只需要2毛多。简直让我产生了在玩异星工厂的爽感。

在这个过程中,我也大概了解了Kubernetes集群和服务架构的一些逻辑,真的是非常方便,怪不得大家都在容器化,这才是真正的DevOps。既然容器这么好,那游戏服务器这边,怎么搞也得上一下吧?于是就产生了这篇日志要讨论的问题。

Web 项目与游戏服务器集群的差异

目前在Web项目中,使用微服务架构已经成为标准做法,简单来说,就是让所有的接口都成为无状态的,那么服务就可以近乎无限的横向拓展,而微服务所依赖的服务发现与负载均衡网关,则为快速拓展带来了非常大的方便。游戏服务器从本质上来说和Web服务器其实并没有非常大的区别,主要的差异大概列一下是以下几点:

  • 游戏不可能做到完全无状态,主要是性能方面考虑。所有数据都只存在数据库或者某个中心节点是几乎不可能的。一个网页,点击一下链接,花费一秒钟打开你可能还觉得挺快的,而游戏你滑动一下摇杆,过一秒角色才动,可能你就想砸电脑了。
  • 游戏的通讯协议一般是直接走TCP或者封装一下TCP on UDP,不太会(也不是没有)走HTTP协议,在频繁通讯的情况下每个HTTP请求都要重新建立TCP连接,每个HTTP包还要带上那么一大坨额外的数据,时间和带宽开销有相对较大,就算考虑到keep-alive可以复用连接,二者的性能还是有明显差距的。(最近看到从Google的QUIC项目升级而来的HTTP/3,是基于UDP的,非常有意思)
  • 游戏服务器没有类似Spring Cloud这样的成熟方案……

这两(三)个问题合并在一起,就让我犯难了。理论上说,我当然希望所有的服务是无状态的,那么TCP也就没关系了,我随便连谁都行。如果有状态的话,我就必须保证同一个用户每次链接的服务都是同一个,这样势必导致需要给每个服务都开放公网连接端口,这些端口还必须有办法让用户知道。如果考虑Kubernetes集群就更完了,每个Container都需要对外暴露端口,这简直没法做了。

Frontd

想了两天(开始写文章的时候是第一天晚上),偶然看到了很久以前其实就看到过的东西……结果豁然开朗

https://github.com/xindong/frontd

感谢沈老师,感谢达达,没想到竟然是这么这么熟悉的大佬们帮我解惑了,解决方案也很容易,只是在出口架设一个网关,每次连接上去以后,先跟他说你要找谁,网关就帮你转发了……理论上和HTTP是一个逻辑。

有些时候,解决方案不是你想不到,是不敢想。

于是周一很开心的写了一天的Go……把这个三年前的项目重新整理了一下,替换了一些依赖,并基于Alpine重新build了镜像,让镜像的体积从257M减小到了7M(多阶段构建大法好!!!)

今天呢,则是build了一天的项目镜像……前面花了一半的时间企图继续使用Alpine打包,结果最后发现Jemalloc不兼容……GG

然后又转而使用Ubuntu,也遇到很多问题,一一解决。镜像传参问题也想到了一个比较好的办法,算是搞定了基本的镜像问题,standalone模式也可以顺利运行了。

明天开始,来解决服务发现问题,并且需要重新改写客户端那边基于frontd网关的连接。

服务发现

服务发现问题解决的比较顺利,除了中途差点操作失误丢失了全部的工作成果,最终竟然是从之前打好的docker image里面把脚本都找回来了……简直万幸,这个故事告诉我们,找回 git 中 staged 的变更只存在理论可能,实际操作中实在太麻烦了……

服务发现本质上要解决的问题是在所有节点共享一份地址簿,当有节点加入或退出的时候,需要根据实际情况实时更新。所有无状态节点都是走Kubernetes服务的,直接通过服务名称即可访问,也是保证高可用的,这部分节点的伸缩,对于Pod外都是完全透明的,不需要动态注册与反注册,只需要订阅地址簿的更新即可。而有状态的节点(比如游戏服务器),在集群中应该是在无头服务的后面,必须要指定到具体的Pod才可以访问,所以这类节点不仅需要订阅更新,也需要动态注册自己。

具体的实现方式是这样的,首先有一个单独的节点作为服务发现的管理节点,称为cluster_manager(暂时这就是一个节点,如果做成高可用就需要解决多节点的数据一致性问题,比较麻烦,这个节点的功能也比较单一,应该不会出现严重的问题,后续有机会可以加强这里的健壮性),其他每个节点都有一个对应的服务发现服务,称为cluster_client。所有节点在启动的时候,都必须先启动cluster_client服务,这个服务会自动向cluster_manager订阅更新。需要注册的节点在订阅之后可以调用接口进行注册,注册成功,则会获得一份地址簿用于更新。后续的更新都会通过之前的订阅自动完成。

成功注册之后那就有个节点下线的时候的反注册问题。正常的下线反注册很简单,就是一个接口调用的问题,但是异常状态下,比如崩溃或者网络连接中断的情况,就必须及时的把这个节点下线。要解决这个问题,就需要一个健康检查的功能,一般的HTTP服务需要维持心跳来刷“存在感”,Skynet使用的是TCP,云风大佬在一个Issue里面给出了一个很好的办法,套用过来就是说,cluster_manager服务在接收到注册后,就会给cluster_client发送一个请求,正常情况下cluster_client不需要回应,这样,当这个节点中断的时候,cluster_manager就会收到一个error,从而得知节点状态异常。顺带着,我把login service到game service的健康检查也顺便做了一下,这样当game service断开的时候,login service就可以及时了解,从而防止推荐不存在的节点给用户。

网关模式的实现

frontd网关模式的实现……就是一把辛酸泪了,理论上是很简单清晰的,泪点都在具体实现上。首先,我研究了很久都没想通为什么frontd连接成功之后不会回应一个状态码,这样的话错误码就无从接收了呀,你接收4个字节,一看不是错误码,哦,那说明连上了,那收到的4个字节怎么办!你还能还给socket不成……或者万一正确的消息恰好就是状态码的一种呢?最后实在无解了,就还是给网关改写了这块功能,也修改了一下相应的协议。

然后呢,frontd的加密使用的是AES算法,具体的应用标准则是基于openssl,这里并没有详细的文档说明到底是怎样得到的最后的base64编码的结果,我所能依赖的只有1、源码中引用的一个叫做go-oepnssl的库;2、文档中给出的一个在线加密网站;3、openssl的官方实现。第一个库基本就不用看了,整个一挂羊头卖狗肉,就单单实现了一个加密也好意思叫go-openssl?而在线加密网站完全只说用了Crypto-js,其他的一概不知,最终我能依靠的就只有openssl了。以下省略N个小时(包括一通宵),之后,终于搞出一个Lua绑定的C库用来生成加密结果了。后续的工作主要就是客户端的对接,顺便解决了一下最近发现的,shell被强制结束后,Skynet进程会成为孤儿进程的问题。一开始我假设了一堆原因,顺便吧UNIX的signal机制好好学习了一番,最后怎么看怎么不对,这为什么会结束不掉呢?苦思许久后灵光一闪,日志服务的logrotate信号好像就是SIGHUP,看了一下果然是的。为了不改Skynet库代码,我在自己实现的日志模块中把Skynet注册的SIGHUP信号恢复为默认了,并重新注册了SIGUSR1信号作为代替。

至此,集群方案的开发部分就已经差不多了,后续的工作主要是尝试在Kubernetes中部署,并合并代码,将现有的客户端通讯替换为集群方案。

想想觉得很有意思,不懂的时候遇到觉得无比巨难的问题,在解决了以后就好像是理所当然的了。人的进步不正式基于此吗:)

最后

提两个小点:

  1. 开始没发现网关方法的时候,为了对外暴露的接口有限,我尝试找寻了一些方法,其中一个叫做LO_REUSEPORT的套接字选项成功吸引了我的注意,网络上所有的文章都把我说的云里雾里,实际尝试确实可以让端口被重复监听,但是会导致收到的消息完全混乱。最终,我还是老老实实去翻了《UNIX 网络编程》,解释得清清楚楚,希望后面有对这个选项感兴趣的同学可以直接去看书……简单来说就是这个选项只有UDP通讯的时候需要启用,TCP绝对不要开就对了。
  2. 看书的时候顺便吧IPv4协议部分又复习了一遍,发现了一个有趣的点,原来127.0.0.1/24(即 127.0.0.0 到 127.255.255.255 )全都是本地环回接口,我实际试了一下,在Windows上,除了127.255.255.255(广播地址)以外,确实都是可以ping通的。这个小知识在当天就派上了用场,我在本地单机尝试的时候,希望和集群保持一致的端口,但是端口不能重复监听,怎么办呢?好办,通常我们都是会开启LO_REUSEADDR的,这样我们在本地只要监听不同的本地环回地址,就可以使用相同的端口的,我们还能在hosts中配置对应的hostname,这样就非常开心了,本地和集群配置完全一致。

一次Redis数据完全丢失的事故

虽然不是我删库,但是还是想跑路

之前可能说过,虽然现在的项目明确最终应该还是要靠MySQL,但是开发期间为了方便,使用Redis做数据落地。

很长一段时间都没有问题,心中隐隐产生了点好像直接使用Redis也没什么问题的感觉。

于是今天就瞬间炸裂了。

早上机房因为一个插线板烧毁,导致断电,不过当时我并不知道具体情况,以为只是普通断网,网好了以后试了试NAS连接没问题,就没有再管了。下午偶然想要更新一下Skynet,结果发现开发服连不上去,仔细一查发现VM宿主机都连不上了,赶紧联系运维去机房看了看,一聊才知道原来是断电了。奇怪的是NAS为什么没问题呢?隐约记得NAS我是设置了断电恢复后自动开机,现在是体会到这个功能的必要性了……下次再出现这种情况,得去把虚拟机宿主服务器也设置一下。

上来以后连上VM看,所有虚拟机都没开,原来VMware ESXi在默认设置下,开机是不会自动启动虚拟机的,查询了一下,把都设置自动启动了。确认虚拟机都启动起来了,也就没再管了。结果过了一会儿,徐哥问游戏服务器的连接问题,我有些纳闷,一看,果然都挂了。这时候正好要去参加一场面试,粗略看了眼好像是Redis问题,systemctl查看果然是Redis没有启动,restart也无效,只好嘱咐徐哥帮忙看一下,准备好材料先去面试。

回来以后问题还没解决,这个问题非常奇怪,系统日志里看Redis只是单纯的启动不了,徐哥查看了Redis日志说是没有权限读取dump.rdb,查看权限竟然是600,所有者和群组都是root。权限设为755后,读取报错,确认应该是文件损毁,改名之后,Redis顺利启动。BGSAVE生成新的dump文件,对比发现,这次生成的文件所有者是正确的Redis,大小也远远超过损毁的文件,看来原来的资料是没救了。损毁的原因猜测应该是断电的时候正好在dump,不过怎么会这么不靠谱呢?仔细去看了一遍Redis有关持久化的文档,以及conf文件,终于搞清楚了,原来是自己的用法不对。

Redis 有两种持久化方案,RDB (Redis DataBase)和 AOF (Append Only File)默认开启的只有RDB,定期全量备份全库,这个从文件名dump也能清楚的看出来,平时非常好用,但是致命的问题就在于……RDB并不保证完整性和一致性。万一在dump的时候断电,那么就是直接的结果……文件损毁。

而AOF就是为了弥补这个缺点而存在的,直接的理解就是记录日志,根据配置可以对每一条记录写一次,或者每秒写一次,在超过指定大小后,还会重写整个文件,防持续追加记录导致文件过大。

找到设置,开启AOF,以后就不怕再断电了。正高兴呢,结果查询了一下,发现Redis竟然数据又消失了……仔细考虑了一下,开启AOF之后,Redis启动时就不再读取RDB,而是根据AOF日志恢复,而现在AOF是空的,那么当然恢复不出任何数据了。这个问题的解决方法也很简单,要么从一开始就开启AOF,要么配置文件中先不开启AOF,而是通过RDB启动起来以后,使用client调用命令手动开启AOF。我这样操作以后发现依然没有数据,这可就奇怪了。再仔细思索一下,心中一凉,完了……又把数据搞丢了。我在上一次发现数据库是空的,然后stop数据库准备不开AOF启动那一次,直接就把空数据库dump了出来,覆盖了有数据的那份……唉……太傻了。

删库有一个好处,我趁机把之前想改的一个key结构给改了,反正都全部重来了,也算苦中作乐吧。好在反正就我们这几个程序策划在里面,给每人发点金币补偿一下吧,哈哈哈。

这一段时间

每次因为什么想要写点什么的时候,总会在脑子中过一圈,然后觉得这也不想写那也写不了,聊聊公司团队的事情吧,顾虑太多;聊聊技术问题吧,自己都觉得写出来也是见笑。什么都不管,先打开网站登个后台顺手点个升级,然后发现,连接错误无法访问——好家伙,阿里云这是把Wordpress整个域名墙了么,升级的小提示点不掉真是浑身蓝瘦。

看看上一篇,3月份,这之后可以说是开始了从项目角度说最好的一段时间了吧,策划和技术都在快速推进。倒是我这边,开始陷入了一点战略战术上都不确切想得清楚自己到底该做什么的境地,开始渐渐有些焦虑。

3月底的时候徐哥过来,客户端开始正式推进,写了个B站爬虫,看MMD分类视频的播放数据,看了《Unnatural》,去参加了出版局的培训,买了打印机,搞定了公司网站ICP备案的迁移,4月的时候思聪突然提出要离开,叽里呱啦,面了一堆美术,找了杨大哥,把事情敲定,20号战神发售,沉迷了一段时间,真不错。

以上……是靠Google历史记录翻出来的……互联网隐私真可怕233

5月开始就是正式开始搞服务器和平台,期间去参加了核聚变,感谢机核大佬,和吹哥吃了个饭,后面继续搞服务器,基本就是安心用战术上的勤奋掩盖战略上的懒惰,当个快乐的码农了,大概在6月底的时候感觉略微有些入门,大体上是理解意思了。

服务器招人是从来没停过,一开始是觉得两个方向,1. 找一个可以全部搞定的人把这个搞定;2. 找一个搞Skynet有点经验的人,按照当前的方向进行下去。结果来说,至今来没找到合适的(残念在于有两个职位其实已经谈好了,结果候选人自己放弃了……)到目前为止,基本上当前项目来说感觉基本上其实已经差不多了,今天我甚至已经在考虑要不要直接招一个搞Java web服务器的来忽悠他转行233。真的无奈啊,游戏服务器怎么会这么难找……神了

写服务器的经历还有值得一说的也许就是确实打破了我对动态语言的偏见吧。刚开始确实是觉得心智压力极大,写到后面也就觉得还好了,不过对打字速度的要求确实是比过去高了不少,哈哈。Lua比我过去想象中的感觉要好很多,已经有些爱上这门语言了,第一次尝试不使用OO范式写项目,感觉也很新奇。总之在编程领域也算是开启新世界的大门了吧。