为什么我要选择Erlang呢?
一、erlang特别适合中小团队创业:
erlang有异常成熟、经过电信级别大规模验证的OTP应用库,只需要很简单的代码就能建立起异常稳定、容错性强、扩展性强、高并发的服务器框架,这也是erlang最宝贵的核心价值所在。
二、erlang是天生的并发语言:
erlang的并发特性是语言级别的,从开发伊始就采用了CSP并发模式, 以进程为单位,进程间没有共享内存,变量不可变的实现方式保证了无锁的并发模型,因此也是异常高效的,换句话说:你只要像平常一样写代码就能并发,完全不用操心任何底层实现,你的代码能完美的并行运行在多核服务器上,如果你能写出漂亮的并发级别的算法和代码(尽量少的顺序代码),那在32核机器上就能跑出32倍性能!!!! Go 语言的并发模型也是取经于Erlang,但是我认为Erlang的并发模型更优秀,因为进程间完全没有共享内存,完全无锁。
三、再介绍下我当初的业务需求:
一款多人在线游戏,一个玩家走一步都要把消息广播给同屏的玩家,玩家聊天,战斗更涉及到大量的消息广播;如何应对?再有一个及其普通却不太容易搞定的的需求:在线玩家列表怎么实现?是啊,你是不是在想用哪种锁合适?提到的两个场景的关键词是:高并发,大量广播;可能你还会想到"锁".
我尝试过在.net下使用完成端口+TPL库+protocol buffer来完成上面的功能,但是并没有通过测试的检验,测试模型是聊天.在收发消息方面,客户端和服务器一对一的收发压力不大,但是一旦开启广播,压力一下就上去了.对象的频繁创建会导致垃圾回收,而垃圾回收会导致CPU和内存都飘忽不定,中间加入对象池会得到一定缓解,但是不能彻底解决问题,然后想到的就是人为干预垃圾回收,判断标准是什么呢?那就是用PerformanceCounter吧,结果发现PerformanceCounter一次调用分配的内存相当大!最后一版的结果是:聊天室模型,一人说话广播给所有人,300人在线能够稳定,人数一多就开始不淡定了.这些都是经过量化分析得出的结果,使用的工具是Visual Studio2010中的Performace Profile工具.
需要解决的第二个问题就是并发加锁,最简单的测试模型就是在线玩家列表.这个问题同样困扰了我很久,尝试各种锁,还是在抛异常,要么就是性能的下降,问题此起彼伏.后续还要解决TCP通信的数据格式,以及粘包等问题......
项目时间紧张,存在的风险很多,要尽快把技术方案确定下来然后去推进别的事情;但是可供选择的方案有C++和Erlang.坦白讲我和团队的基础如果使用C++方案,一定能搞出来,但是排错和性能优化将是一个巨大的挑战.那么Erlang呢?从开篇引用的那段文字看,好像这就是我需要的,简单了解了一下语法,还是很惊喜,由于之前对F#有过接触,一下感觉很亲切.而且我特别关注到:
优点:
1.面向并发,有成熟而且久经考验的框架可供使用,网络部分已经经过了良好封装
2.内存缓存解决方案进程字典,前者的读写速度是50NS-100Ns级别的
3.对二进制数据解析的语法是直观,简单,强大(游戏中有大量的二进制数据要处理
4.没有共享内存! 没有锁!(我们在代码中没有过显示使用锁)
缺点
1.从一种语言过渡到另一种语言,会有各种不爽:
2.控制逻辑简单只有if 和 case ,而且有if没有else,没有continue break goto
3.包括kernel库和standlib库在内,很多函数和变量的命名和传统语言不一样
因此我们就决定了采用erlang来重新写一套全新的架构,事实证明当初的决定是无比正确的,一个极少需要重启、能热更、稳定的游戏服务器实在是太重要了,而且开发过程和维护是如此的快速和轻松,我们的团队一致认为:从来没有想过开发会是这么一件愉快的事情!
既然Erlang已经被我“吹”的快飞起来了,为什么还要使用Go?
鉴于Go语言已经妇孺皆知了,我也就不介绍了,大概说说我自己的情况,我这人没啥其他兴趣爱好,业余时间绝大部分都花费在所谓的“程序员要不停的学习才不会落伍”上,因此在11年的时候,知道了go,断断续续学习了一年后,Go1.1版本出来后,发现改进很大,就开始认真研究并常年混迹在google-group及国外大牛的博客世界中,自我感觉还可以。当然我绝对不是Go的“朝圣者”,也发现Go确实不是非常完美,具体可以参见“为什么我要放弃Go“,此文作者的观点我虽然不敢完全苟同,但是有些观点还是赞同的,比如说很多Go爱好者是非常护短的,如果你敢说什么“坏话”,就等着被查水表吧 ;)。
项目 | nodejs | python | c++/ruby | erlang | golang |
---|---|---|---|---|---|
体系成熟 | 4 | 3 | 5 | 5 | 3 |
开发效率 | 5 | 5 | 3 | 4 | 5 |
性能 | 3 | 3 | 5 | 5 | 4 |
加密发布 | 3 | 0 | 4 | 3 | 5 |
逻辑简单 | 5 | 5 | 3 | 4 | 5 |
易学易用 | 5 | 5 | 2 | 5 | 4 |
跨平台 | 5 | 5 | 5 | 5 | 5 |
从上表中可以看出 erlang和go之间的互补性还是很好的,Go的体系成熟度确实还有待提高
由于Erlang和Go都是非常棒的语言,这里就出现一个问题:二选其一还是物尽其用?经过深思熟虑后,我和团队选择了后者。首先,erlang的OTP写服务器并发框架非常之简单、稳定且高性能,erlang的Mnesia数据库也是很轻量:速度很快,分布式简单,使用起来也很原生态(是Erlang标准库支持的),所有的这些都能把程序员从繁琐的工作中解放出来,但是,erlang也有个挺重要的问题(在不同业务场景中此问题也许很突出,也可能完全无关紧要,至少85%的情况下不算一个问题):它是虚拟机语言,对于顺序代码的执行速度只有C的七分之一,虽然可以利用多核的优势,但是在大型mmorpg中,消息密集时,CPU的瓶颈还是挺明显的,会影响玩家顺畅的体验感觉(ARPG)。
因此我就想如果逻辑这部分用Go来写,是不是可以很好的利用这两个语言的优点进行互补?心动不如行动,由于我们的erlang游戏架构的藕合度还是挺低的,因此分离出来地图服务器,用Go重新实现了下,通过socket跟erlang架构部分进行通信,发现效果异常之好,Go的性能、并发的原生支持再配合上erlang写游戏框架,在性能上已经绝不亚于C++框架,但是后者大家都懂,中关村程序员据说平均寿命50多岁,很大的一部分原因是因为这个。
以后的路怎么走?
混合型编程会是以后的主流,因为没有哪个语言是完美的,包括被众多“朝圣者”所推崇的Go,如果我们能根据自己的业务场景,选对合适的语言,那不敢说事半功10倍,至少事半功倍应该是有的,所以不要被主流语言(Java,C++)禁锢了我们的世界,局限了我们的创新,如果能做到轻松愉快的开发,那这个世界该多美好!!