elixir 高可用系列(三) GenEvent
概述
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
elixir 高可用系列(三) GenEvent的更多相关文章
- elixir 高可用系列 - 目录
1. elixir 高可用系列(一) Agent 2. elixir 高可用系列(二) GenServer 3. elixir 高可用系列(三) GenEvent 4. elixir 高可用系列(四) ...
- elixir 高可用系列(五) Supervisor
概述 OTP 平台的容错性高,是因为它提供了机制来监控所有 processes 的状态,如果有进程出现异常, 不仅可以及时检测到错误,还可以对 processes 进行重启等操作. 有了 superv ...
- elixir 高可用系列(四) Task
概述 之前学习的 Agent,GenSever以及GenEvent,都是用来管理状态或者处理消息的. 但是在很多时候,我们需要的是执行某个任务,这时如果使用 GenSever 或者 GenEvent, ...
- elixir 高可用系列(二) GenServer
概述 如果我们需要管理多个进程,那么,就需要一个专门的 server 来集中监控和控制这些进程的状态,启停等. OTP 平台中的 GenServer 就是对这个 server 通用部分的抽象. 利用 ...
- elixir 高可用系列(一) Agent
概述 elixir 本身是一种 immutable 的语言,默认情况下,进程间是不共享任何状态的,进程之间通过消息来交互. 而 Agent 则封装了一种进程间共享状态的方式,通过这种方式,不用显式的写 ...
- (5.8)mysql高可用系列——MySQL中的GTID复制(实践篇)
一.基于GTID的异步复制(一主一从)无数据/少数据搭建 二.基于GTID的无损半同步复制(一主一从)(mysql5.7)基于大数据量的初始化 正文: [0]概念 [0.5]GTID 复制(mysql ...
- Mycat高可用解决方案三(读写分离)
Mycat高可用解决方案三(读写分离) 一.系统部署规划 名称 IP 主机名称 配置 192.168.199.112 mycat01 2核/2G Mysql主节点 192.168.199.110 my ...
- 暑假打工 2 个 月,让我明白了 Keepalived 高可用的三种路由方案
暑假打工 2 个 月,让我明白了 Keepalived 高可用的三种路由方案 这是悟空的第 158 篇原创文章 原文链接:首发悟空聊架构 官网:www.passjava.cn 你好,我是悟空. 前言 ...
- keepalived高可用系列~ keepalived+proxysql
一 简介:介绍下高可用通用的方案 二 目的:一个中间件提供服务,故障后,另一个中间件提供服务 三 手段: 应用keepalived的vrrp_scripts服务 四 具体配置 global_defs ...
随机推荐
- MySQL大数据分页的优化思路和索引延迟关联
之前上次在部门的分享会上,听了关于MySQL大数据的分页,即怎样使用limit offset,N来进行大数据的分页,现在做一个记录: 首先我们知道,limit offset,N的时候,MySQL的查询 ...
- 给pcm格式文件加wav文件头
#include <stdlib.h>#include <stdio.h>#include <string.h>void main(){ //wav头的结构如下所示 ...
- 《Linux内核设计与实现》读书笔记 第十七章 设备与模块
一.设备类型 1. Unix系统 - 块设备 - 字符设备 - 网络设备 2. 块设备 通常缩写为blkdev,它是可寻址的,寻址以块为单位,块大小随设备不同而不同:块设备通常支持重定位操作,也就是对 ...
- 循序渐进Python3(三) -- 3 -- 内置函数
上一篇我们又介绍了26个Python内置函数.现回忆一下吧: 1.all 2.any 3.ascii 4.bin 5.bool 6.bytes 7.bytearray 8.callable 9.chr ...
- asp.net Gridview 的用法
留个档. <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="Fa ...
- RHEL 7.0 本地配置yum源
RHEL 7.0 本地配置yum源 yum简介 yum = Yellow dog Updater, Modified 主要功能是更方便的添加/删除/更新RPM包. 它能自动解决包的倚赖性问题. 它 ...
- vim--golang代码补全
我想说,我折腾了很久编辑器,试了九种办法 最后我只成功了一种 但我依然想就我混乱的逻辑做下整理 一.一开始,我试图入手ipad编码软件,大概9美金吧,叫Textastic.我试图用它的近亲来试验Tex ...
- 获取datagrid选择行
var rows = $('#dg').datagrid('getChecked'); var ids = ''; for (var i = 0; i < rows.length; i ...
- 屏蔽input导致的回车提交事件
onkeypress="if(event.keyCode == 13) return false;"
- JavaWeb---图书馆管理系统
写在开头,以后每天写记录. 今天,初步了解了一下,项目需求,用现在自己所学的知识,很多还不能做出来. 先用目前的知识,一步步的做出来,不断的完善,今天遇到的问题: 任务分析: 01.list页面的ad ...