前言
这里对Erlang概念的掌握只是能基本看懂EMQ写的是什么就可以了,不需要具备二次开发EMQ的能力,达到开发的熟练度还需要花费大量时间。
一、Erlang基本了解
1)首先要知道Erlang是用C语言写的,所以它的大部分语法都和C语言近似。
2)Erlang发明的目的就是分布式、并发的,编程的时候用单机编程思路就好了,分布式是透明的,所以适合用来写分布式并发程序。
3)Erlang的核心是进程,这里的进程是Erlang自己的概念,和Linux的系统进程是完全不同的,比C语言的线程切换快得多。
4)Erlang的运行时环境是一个虚拟机,类似Java的一次编译随处运行。
二、Erlang/OTP
1、OTP
OTP (Open Telecom Platform,开放电信平台)是一个开源的 Erlang 分发和一个用 Erlang 编写的应用服务器,由爱立信开发。
OTP 包含:
- 一个 Erlang 解释器
- 一个 Erlang 编译器
- 服务器之间的通讯协议
- 一个 Corba 对象请求代理
- 名为 Dialyzer 的静态分析工具
- 一个分布式的数据库服务Mnesia
- 大量的开发库
其中最重要的就是Mnesia了,这是一个分布式数据库,对编程透明,编程就好像在访问一个集中式数据库一样,底层数据同步由Mnesia完成,在EMQ中被大量使用。
OTP帮助解决了容错的问题。
2、OTP设计原则
OTP设计原则是面向行为(behavihour)编程,行为类似于接口的概念,EMQ完全依照OTP设计原则进行的开发。
1)代码的物理组织方式
doc:存放程序文档和配置文件
include:存放.hrl头文件(类似C语言.h),一般包含大量Record(类似C语言struct)和宏定义(类似C语言宏定义)
priv:类似Reference文件夹,存放需要引用的第三方类库
src:源代码,包括.app.src入口文件、.erl模块文件
test:单元测试代码.erl文件
ebin:编译的目标文件夹,存放.app和.beam文件
来观察下EMQ2.3.11的代码结构,就是这样组织的:
2)标准的Erlang/OTP行为
gen_server:用于实现C/S结构中的服务端
gen_fsm:用于实现有限状态机
gen_event:用于实现事件处理功能
supervisor:用于实现监督树中的监督进程
gen_statem:新版本中的有限状态机
3)代码的逻辑组织方式
本质是如何组织进程,OTP的进程组织方式是监控树(Supervision Tree),分为Supervisor和Worker两类:
1)Worker:实际执行业务逻辑的进程。
一般使用gen_event,gen_fsm或gen_server等行为来实现。
2)Supervisor:监督子进程执行的监督进程,简称督程,如果Worker出错,则以一定方式进行重启。
监督的子进程可以是Worker,也可以是另一个Supervisor,使用supervisor行为来实现的话会有一套接口方法标准集,包括跟踪、错误报告之类的功能。
重启的策略有四种:
【one_for_one】如果一个子进程停止,则只重启该进程
【one_for_all】如果一个子进程停止,则其他所有子进程都停止并全部重启
【rest_for_one】如果一个子进程停止,则启动顺序在它之后的所有其他子进程都停止并重启
【simple_one_for_one】简化版one_for_one,所有子进程都是同样的类型且都是动态添加的实例。
EMQ2.3.11采用的【one_for_one】—— src/emqttd_mod_sup.erl:
%%--------------------------------------------------------------------
%% Supervisor callbacks
%%--------------------------------------------------------------------
init([]) ->
{ok, {{one_for_one, 10, 100}, []}}.
三、Erlang/OTP的数据库
Erlang的数据库有两种:
【ETS】内存K-V数据库,存储Erlang Term
【DETS】基于磁盘的ETS
OTP数据库:
【Mnesia】基于ETS和DETS的分布式数据库
EMQ中ETS、Mnesia两种数据库被大量运用。