您现在的位置:首页 --> 查看专题: Erlang
Erlang公平调度是它的哲学(或者说坚持)之一,从第一个版本的beam代码的时间片分配和抢占开始,到最近版本的bif对公平性的坚持(比如R17版binary_to_term就大幅做了修改,代码复杂很多,执行效率也有下降,但是在碰到大的binary的情况下,通过Trap机制会让出执行权,排队后再回来断点续作), nif(加入扣除时间片的接口),这些努力保证了erlang系统是个公平的系统。 很多终端系统和业务会受益于这个哲学,如云计算。不管用户大小和业务的负载情况如何,系统性的公平性可以保证每个用户有机会被服务,对用户有很好的体验。
erlang的io是薄薄的一层c封装,每个file:read或者pread的时候,会把读写的具体参数发给driver, 然后等待driver发消息,返回IO结果。 每个io操作会涉及: 发消息+driver做IO操作+等消息 三个阶段。 所以如果我们的io操作太小,发消息和等消息的代价就会大,违反erlang的”小消息,大计算”的设计理念,低性能是一定的。
Erlang的集群默认情况下是全联通的,也就是当一个节点加入集群的时候,介绍人会推荐集群里面所有的节点主动来和新加入的节点建立联系, 具体点讲那就是net_kernel模块负责节点间的通道的建立、检查、断开并提供monitor_node语义。
我们知道erlang的消息发送是透明的,只要调用Pid!Msg, 虚拟机和集群的基础设施会保证消息到达指定的进程的消息队列,这个是语义方面的保证。那么如果该Pid是在别的节点,这个消息就会通过节点间的rpc通道来传递。rpc模块就是基于erlang的这个语义在上面实现了远程函数调用。
这么多年过去了,社区还在讨论erlang是不是小众语言,各种怀疑的时候,whatsapp已经把erlang用到了极致。 whatsapp是什么? 参见它的 官网 WhatsApp Messenger is a cross-platform mobile messaging app which allows you to exchange messages without having to pay for SMS. 更为搞笑的是 主要开发者Rick Reed(rr@whatsapp.com),之前在Yahoo!, SGI工作,有着深厚的系统性能的背景。
继续上一次的sys模块升级的话题,我们再讨论一下升级基本原理,了解一下code和code_server模块。 简单升级 上文也说到过,如果升级未改动 State 里的内容,你可以这样升级。 在集群的每个节点内(当然也可以通过 rpc) 拷贝 beam 到线上的 ebin 目录。 code:purge(Module). code:load_file(Module). 让代码触发 Fully qualified function calls,走到新的 beam 代码。 如果你想省略后 2,3 步,可以利用mochiweb的 reloader 模块进行自动加载。 升级的原理 结合code_server代码来研究一下升级的原理。 erlang 可以同时允许两套代码同时加载运行在虚拟机内部运行, 一套被成为老版本代码 , 一套被成为当前版本代码,也成为最新代码。
gen_fsm和gen_server非常的类似, 在gen进程递归调用loop函数的过程中,除有StateData还额外有一个StateName的atom, 它决定了下次执行的函数. 另外一个不同之处是, gen_server程序是由调用进程向gen进程发送消息, 一种cs模式的调用关系,而gen_fsm程序中这个发送消息的通常都是gen进程本身. init 初始化过程和gen_server很类似, 区别是init返回必须获得一个当前状态StateName, 这样才能继续接下来的事件处理.
阅读OTP源码可以帮助你写出更好、更健壮的erlang程序.下面一系列文章就gen_server、gen_fsm、supervisor的源码进行分析, 从erlang级别解释其工作原理, 所有的完整流程图在这里, 第一次写erlang方面博文有错误请帮忙指出. 为什么从gen_server它开始, 因为gen_fsm和它很类似, 而supervsisor本身是一个gen_server. init 图示为一个叫Mod的模块, 它是一个gen_server程序, 绿色方格为调用进程(客户进程), 黄色方格为spawn出的gen进程(服务进程). 不同的泳道表示函数所隶属的模块, 通过这个图可以清晰的看出各个模块至之间的相互调用, 图是使用gliffy所画。
supervisor实际上是基于gen_server的系统进程,监控子进程的退出状态并设置一定的重启机制。 init 在这个例子里Mod模块是一个sup程序,它的启动会调用supervisor:start_link,而start_link实际上调用的gen_server:start_link并存入Mod模块的名字和参数. 从前面的文章我们可以知道, spawn出来的gen进程会先调用supervisor:init函数. 接着把gen进程设置为系统进程, 这样就可以捕获子进程退出信号, 然后根据Args里的Mod模块名和参数,再次调用到Mod:init. Mod的init函数返回的是一个{ok, SupFlags, StartSpec}的元组. SupFlags是supervisor管理的进程的启动策略和可重启的范围窗口,StartSpec是一个列表,保存多个子进程的MFA等信息.
最新的Erlang虚拟机(R15B01)很大的一个改进就是加入了对dtrace探测点的支持了, 具体参见这里, 主要目标是方便在生产实践中定位复杂的性能问题。 目前Erlang的虚拟机的探测点支持Linux的systemtap和freebsd的dtrace,我们刚好能够享受的到。
Erlang虽然号称N个9的稳定性,但是在实际使用中还是有很多机会看到Erlang Crash了的,其中和VM相关的Crash 十有八九是由于内存使用过量,导致系统服务分配内存导致的。Erlang的内存分配测量是集中批发,零售给各个VM部件,包括用户进程和ETS数据库等内存消费大户。VM的内存增长是以fib方式上升的,一旦你的内存使用到G级别,那么之...
rebar和common_test配合起来用的很爽。
默认情况下Erlang的集群访问是全授权的,只要cookie认证过了后,新加入的节点可以访问集群里面的任何机器,这给运维带来很大风险。目前erlang有二种方法可以限制 1. IP网段限制,参看这里 2. 节点名称限制。
我们知道Erlang的调度器是公平的,当进程的时间片用完了后,会强制切出,但是这个粒度是比较粗的。比如说进程进行了大量的Io操作,这个操作换成时间片是不准确的,会导致某些CPU计算密集型的比较吃亏,IO密集型的合算。 为了避免这...
Erlang Shell下有很多内置的命令,在平时交互的时候很好用,文档里面都是一行带过,大家可能没什么感觉。
match_spec是个erlang term过滤器,可以让用户来自己选择需要匹配什么,需要从term里面抽取什么数据。那同学可能就有疑问了,Erlang的函数不是很强大吗,它能做的函数也能做,那为什么要重新费劲做一个呢?Erlang实现这个match_spec得原因有2个:1. 运行效率 2. 小巧可以在运行期使用。
gen_tcp:unrecv是个未公开的函数,作用是往tcp的接收缓冲区里面填入指定的数据。别看这小小的函数,用起来很舒服的。 我们先看下它的代码实现,Erlang代码部分: 运行期c代码部分: 实现上很简单,就是透过tcp ctl命令往驱动接收缓冲区里面填数据。 但是什么是gen_tcp接收缓冲区, 它的大小是多大呢? 在回答这个问题之...
[ 共27篇文章 ][ 第1页/共2页 ][ 1 ][ 2 ]
近3天十大热文
- [69] Twitter/微博客的学习摘要
- [65] find命令的一点注意事项
- [64] 如何拿下简短的域名
- [64] IOS安全–浅谈关于IOS加固的几种方法
- [62] Go Reflect 性能
- [62] android 开发入门
- [61] 流程管理与用户研究
- [59] Oracle MTS模式下 进程地址与会话信
- [58] 读书笔记-壹百度:百度十年千倍的29条法则
- [58] 图书馆的世界纪录
赞助商广告