设为首页 收藏本站
查看: 980|回复: 0

[经验分享] Erlang 消息接口和 Stackless Python 的 Channel 比较

[复制链接]

尚未签到

发表于 2017-5-5 10:46:52 | 显示全部楼层 |阅读模式
Erlang 和 Stackless Python 有一定相似之处,都使用轻量级线程和消息传递(Stackless Python 当然也可以使用共享变量)。
简单例子:

# 摘自:http://www.stackless.com/wiki/Channels
import stackless
def Sending(channel):
print "sending"
channel.send("foo")
def Receiving(channel):
print "receiving"
print channel.receive()
ch=stackless.channel()
task=stackless.tasklet(Sending)(ch)
task2=stackless.tasklet(Receiving)(ch)
stackless.run()


-module(message).
-export([start/0]).
sending(Pid) ->
io:format("sending~n"),
Pid ! foo.
receiving(Pid) ->
io:format("receiving~n"),
receive
X ->
io:format("~p~n", [X])
end,
Pid ! done.
start() ->
Pid = spawn(fun() -> receiving(self()) end),
sending(Pid),
receive
X -> X
end.


Erlang 的消息是通过进程邮箱(mailbox)来传递的,每进程绑定一个邮箱。
Stackless Python 消息通过 Channel 传递,Channel 是可以任意创建的,这有一个优点是你可以在同一个进程中使用数据 Channel 和控制 Channel,甚至根据功能来分割。
还有个更好的场景说明它的好处,在一个 server S 进程中向另一个 server X 发送请求,server S 的 mailbox 可能同时存有来自 client 和 server X 的消息,其它语言不一定能很方便地实现 Selective Receive,接收会比较麻烦,即便是 Erlang,这也是有成本的。
如果在向 server X 请求时创建一个新的 Channel 用来接收消息,就完全没有这个麻烦了,Erlang 中要实现这个功能应该也不是麻烦事,又造了一个轮子。
Erlang也可以在每个消息到来时,创建一个进程来处理,也可以避免这个问题,和创建 Channel 效果是一样的。
在使用 ucontext 实现的轻量级线程环境中,还是尽可能减少线程创建的开销,创建一个 Channel 很容易,实现多个 Channel 的 Poll 就更强大了。Channel 还可以使用泛型实现,约束传递的类型。
-----------------------------------------------------
补上我的Channel C++实现介绍,待整理。

template <class T>
class ChannelT : public Channel {
public:
// ...
void Send(const T& v);
T Receive(int timeout=-1);
};


使用:

typedef ChannelT<int> IntChannel;
typedef shared_ptr<IntChannel> IntChannelPtr;
void process1(IntChannelPtr channel) {
for(int i=0; i<10; i++) {
channel->Send(1);
Sleep(1000);
}
channel->Send(-1); // 退出消息
}
void process2(IntChannelPtr channel) {
while (true) {
int i = channel->Receive();
// ...
}
}
IntChannelPtr channel = new IntChannel;
SPAWN(&process1, channel);
SPAWN(&process2, channel);

这和 mailbox 相似,不过process1可以省去一个 mailbox。

使用Channel名字:

Cid cid;
// Channel名字注册
void foo_process() {
ChannelT<int> channel;
cid = channel.cid;               // 给其它进程使用
RegisterChannel("foo", channel); // 注册Channel名字,也可以使用ID
int i = channel.Receive();
// ...
}
ChannelT<int> channel("foo"); // 通过名字发送给Node内Channel
channel.Send(1);
ChannelT<int> channel(cid);   // 通过Channel ID发送
channel.Send(1);

Channel名字代替了进程名字,ChannelID代替了ProcessID,以前每创建一个进程就要生成一个PID,现在只有使用Channel才生成CID,Channel的创建和销毁开销比进程小。多个进程在同一个Channel上等待消息时,进程要挂在Channel的等待链上。
直接使用远程Channel:

ChannelT<int> channel("foo@172.16.1.5");
channel.Send(1);


Channel也可以传递到其它Node上,对方得到此Channel时直接调用它的Send就可以发送消息回来。
在通讯层面上,Channel是逻辑概念,它通过Node之间的连接来传递数据,和Erlang相似。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-373361-1-1.html 上篇帖子: python练习贴07 解析命令行参数 下篇帖子: python中判断一个运行时间过长的函数
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表