elixir 高可用系列(三) GenEvent
2016-05-25 09:00
253 查看
概述
GenEvent 是事件处理的通用部分的抽象。通过 GenEvent ,我们给已有的服务 动态 的添加 事件处理。
GenEevent 和 GenServer 的区别
之前已经介绍了 GenServer ,GenServer 和 GenEvent 的主要区别在于:GenServer 是服务器的抽象,除了封装处理 同步/异步 事件的方法之外,还封装了服务器本身的启动/停止等方法。
GenEvent 是事件的抽象,封装了 同步/异步 事件的处理方法,GenEvent 可以绑定到任何服务器上,从而动态的 添加 服务器的处理方法。
基于上述的区别,GenEvent 和 GenServer 的应用场景也不同。
GenServer 可以帮助我们快速的创建服务,它类似于一个服务的脚手架,使用 GenServer,构建服务时,只需关注服务本身的业务即可
GenEvent 可以用于给现有的服务动态添加处理方法,也可以用于抽象多个服务的共通处理
GenEevent 示例
事件管理器
通过 GenEvent 创建一个事件管理器,将此事件管理器添加到现有进程中,现有进程就有了处理相应事件的能力。简单示例如下:
接收到 :hello 则返回 :world
接收到 :world 则返回 :hello
接收到 其他消息 则返回 "error msg"
defmodule HelloEvent do use GenEvent def handle_event(event, parent) do case event do :hello -> send parent, :world :world -> send parent, :hello _ -> send parent, "error msg" end {:ok, parent} end end
测试过程:
# 启动一个空的事件管理器 iex(1)> {:ok, manager} = GenEvent.start_link {:ok, #PID<0.87.0>} # 发送 :hello 消息 iex(2)> GenEvent.sync_notify(manager, :hello) :ok # 没有任何反应,因为事件管理器中没有任何 handle 来处理消息 iex(3)> flush :ok # 给事件管理器增加一个handle,同时将当前进程PID作为事件处理的状态 iex(4)> GenEvent.add_handler(manager, HelloEvent, self()) :ok # 发送 :hello 消息 iex(5)> GenEvent.sync_notify(manager, :hello) :ok # 事件管理器处理了 :hello 消息,并返回 :world 结果 iex(6)> flush :world :ok # 发送 :world 消息 iex(7)> GenEvent.sync_notify(manager, :world) :ok # 事件管理器处理了 :world 消息,并返回 :hello 结果 iex(8)> flush :hello :ok # 发送 :test 消息 iex(9)> GenEvent.sync_notify(manager, :test) :ok # 事件管理器对于 :hello 和 :world 以外的消息都返回 "error msg" iex(10)> flush "error msg" :ok
上面测试中用的发送消息的方法都是同步方式 sync_notify ,通过异步方式 notify 发送消息也是一样的, GenEvent 的 handle_event 接收同步和异步的消息。
事件流
事件流就是将 GenEvent 的事件转入到流中,这样,就可以通过处理流的方式来处理事件。比如上面的例子,通过 GenEvent 的 stream ,可以不定义 defmodule HelloEvent 也实现上面的功能。
上述测试过程可以改为如下:
iex(1)> {:ok, manager} = GenEvent.start_link {:ok, #PID<0.59.0>} iex(2)> stream = GenEvent.stream(manager) %GenEvent.Stream{manager: #PID<0.59.0>, timeout: :infinity} iex(3)> nil iex(4)> spawn_link fn -> ...(4)> for x <- stream do ...(4)> case x do ...(4)> :hello -> IO.inspect :world ...(4)> :world -> IO.inspect :hello ...(4)> _ -> IO.inspect "error msg" ...(4)> end ...(4)> end ...(4)> end #PID<0.71.0> iex(5)> GenEvent.sync_notify(manager, :hello) :world :ok iex(6)> GenEvent.sync_notify(manager, :world) :hello :ok iex(7)> GenEvent.sync_notify(manager, :test) "error msg" :ok
可以看出,我们没有给 GenEvent 绑定任何的 handler,而是在 GenEvent 的事件流中对所有消息进行了处理。
GenEvent 中事件流的特性是 erlang 中所没有的。
总结
除了上面用的 handle_event 和 stream, GenEvent 中还有其他的实用的 Functios 和 Callbacks具体参见:http://elixir-lang.org/docs/stable/elixir/GenEvent.html
来源:http://blog.iotalabs.io/
相关文章推荐
- 32个FPGA开源网站
- 第11课:Spark Streaming源码解读之Driver中的ReceiverTracker架构设计以及具体实现彻底研究
- 《大型网站技术架构:核心原理与案例分析》笔记
- Web Bench (网站压力测试工具)
- 《高性能网站建设指南》读后总结
- 常见学习网站收集
- 零基础建站教程,教你最快速度做好企业网站
- 从技术细节看美团的架构
- 震惊:2/3 被黑的网站隐藏着后门
- 基于WinSrv2016(TP)构建的“超融合基础架构”
- 基于WinSrv2016(TP)构建的“超融合基础架构”
- mysql 高可用方案漫谈(一) 转阿里云
- 基于WinSrv2016(TP)构建的“超融合基础架构” 推荐
- LVS基础及LVS+Keepalived实现双主高可用负载均衡
- Linux性能及调优指南(翻译)之Linux内存架构
- mybatis架构介绍
- keepalived 高可用配置实例
- 给飞驰的法拉利换引擎 - 谈边做业务边做架构重构(2)—— 合纵连横
- 支付宝系统架构
- Spark Streaming源码解读之Driver中的ReceiverTracker架构设计以及具体实现彻底研究