我对Erlang和Gevent的感受

当然它们是很不一样的东西。

上一篇文章中我也表述对这种的喜爱。

Erlang

Erlang大概是2012年接触的。然后就被震撼了:

  • 简单的语法
  • 随意的spawn erlang process
  • 基于消息传递数据
  • 模式匹配
  • 递归
  • 优雅的二进制处理
  • 强大的OTP框架
  • 分布式支持
  • 自带NOSQL

在学习了Erlang后,总是想着用Erlang搞点事情出来,
于是先后有了:

在不断的学习使用 Erlang, Gevent的过程中,我也有了自己的感受和看法,我就依次讲讲几个印象深刻的地方:

简单的语法

Erlang没有多少语法糖,直接了当,看别人代码很容易。
(特别是基于OTP的项目)

虽然Python基础语法也很简单,并且哲学就是干一件事情只有最好的一个办法。但是Python的各种语法糖会让你看别人代码不是那么行云流水般流畅。

比如Python用了三年多了,前几个月才知道还可以这么写:

with A() as a, B() as b, C() as c:
    pass

基于消息传递数据

Pid ! MyData

如此简洁的语法, 可以在一个Erlang Node内,跨Node,跨机器发送消息。 MyData 是任何Erlang term。 也就是任意Erlang合法数据。

模式匹配 & 递归

-module(fibo).
-export([start/1]).
-vsn(1.1).
 
start(Num) ->
    ResultList = start(Num, 0, []),
    Result = lists:sum(ResultList),
    io:format("~p~n", [ResultList]),
    io:format("~p~n", [Result]),
    ok.
 
start(0, _, Result) ->
    [0 | Result];
 
start(1, _, Result) ->
    [1 | Result];
 
start(Num, 0, Result) ->
    start(Num, 1, [0 | Result]);
 
start(Num, 1, Result) ->
    start(Num, 2, [1 | Result]);
 
start(Num, Acc, [H1, H2 | _Tail] = Result) when Acc =< Num ->
    start(Num, Acc + 1, [H1 + H2 | Result]);
 
start(_, _, Result) ->
    lists:reverse(Result).

这个简单的例子就说明了模式匹配和递归是多么的符合人的自然思维。而且在模式匹配期间就可以从列表元组中提取自己所需的数据。

模式匹配的痛苦

Erlang程序内部自己的匹配真的很爽,但是如果遇到需要去 使用
一些 通用数据格式协议 (比如 protobuf, msgpack) 要和其他语言交互的时候,那真是遇到恶魔

比如一个 protobuf 的定义如下:

message MyMessage {
    required int32 id = 1;
    required string name = 2;
    optional int32 age = 3;
}

Python中是这样来打包/解包数据的:

# 打包
msg = MyMessage()
msg.id = 1
msg.name = "hi"
data = msg.SerializeToString()

# 解包
msg = MyMessage()
msg.ParseFromString(data)

print msg.id
print msg.name
print msg.age

Erlang是这样的:

%% 打包
Data = proto_pb:encode_message({
    mymessage,
     1,
     <<"hi">>,
    undefined,
    }).
%% 解包
{mymessage, Id, Name, Age} = proto_pb:decode_cmd(Data).

好,我们现在在 MyMessage 中加一个域:

message MyMessage {
    required int32 id = 1;
    required string name = 2;
    optional int32 age = 3;
    optional int32 gender = 4;
}

Python 程序不用修改, Erlang 必须修改。因为要全部匹配啊。

在与他人合作的时候,如果采用protobuf, msgpack,这些数据格式,那么修改消息定义,对Erlang就是个灾难!

虽然我在工作中有着很大的自主权,选择自己喜欢的技术,但是正是由于这个原因我没在大项目中用过Erlang。

当然,还是自己Erlang技术不过硬。

优雅的二进制处理

我就举一个简单的例子。获取以大端序表示数字5的 4bytes 长的binary
Python中这么做:

import struct
fmt = struct.Struct('>i')
binary = fmt.pack(5)

Erlang:

<<5:32>>.

当然你也可以明确的写成

<<5:32/integer-big>>

这不过这是默认行为而已。

是不是觉得太方便了,Python 的 struct那一大堆格式谁TM记得住啊。你心里是不是窃喜 用erlang写socket发包收包处理包头方便多呢? 骚年, Erlang在建立socket如果指定了 {packet, N} 参数,如果N是 1,2,3,4这写数字,那么发数据添加包头,收数据去除包头已经帮你搞定了!

得益与 模式匹配, 你可以这样:

<<A:16, B:16, C/binary>> = <<D>>
%% A 是 D 的第一和第二字节
%% B 是 D 的第三和第四字节
%% C 是 D 的第五到最后剩下的字节
%% 当然D的长度得》=4 字节。否则会报错。

Python 里有 列表解析, Erlang里也有,并且更强大。
而且 Erlang 还有 二进制列表解析

强大的OTP框架

gen_server, gen_fsm, gen_event, supervisor 这些模式组成了OTP的分层架构。它让你写的程序思路清晰,各个组件分工明确。


Gevent

然后在回来看看Gevent。

我先学的Erlang,然后才看的Gevent这个Python的库。
刚开始学Gevent的时候总是要和Erlang去对比,觉得这么库很难理解啊。比如:

  • 我在Python shell中 gevent.spawn一个函数,它怎么不运行? 按照自然的思维就是spawn后就应该要运行啊。Erlang就是这样的

  • 为什么spawn出的协程要join,一调用join就会把整个python process阻塞住。丝毫感觉不到异步啊。

在学习两次失败后,后来终于想明白了:

  • shell 中spawn不运行,是因为gevent 的event loop没有跑起来,无法去调度greenlet。

  • join就是在启动gevent 的 gevent loop,一旦gevent loop通过其他方式启动起来了, 那么就可以在程序中自然的spawn进程。新spawn的 greenlet 会被调度执行。

当跨过这个障碍后,学习和使用Gevent容易了很多。

得易于Python这么有好的语言,大量的库,还有Pycharm这么优秀的IDE。 (我以前是VIM死忠。。。),再加上gevent这么给力的库,写并发真是轻松惬意啊。

然后就有了基于Gevent的项目:

最近对Gevent又有了新的感悟。

所以有了这篇文章,以及用了一天时间将 codebattle 的服务器写了个Gevent的版本 codebattle-server-python

结论

Erlang很好,天生就是为了服务器编程而生。
但从我上面的 模式匹配 的描述,以及Python的易用性,
以后会更多的用Gevent


最后附上一个 激情视频

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容