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 ...
随机推荐
- 上传图片HTML <form> 标签的 method 属性
<!DOCTYPE HTML><html><body> <form action="/example/html5/demo_form.asp&quo ...
- 8天掌握EF的Code First开发系列之2 简单的CRUD操作
本文出自8天掌握EF的Code First开发系列,经过自己的实践整理出来. 本篇目录 创建控制台项目 根据.Net中的类来创建数据库 简单的CRUD操作 数据库模式更改介绍 本章小结 本人的实验环境 ...
- c# & Fizzler to crawl web page in a certain website domain
使用fizzler [HtmlAgilityPackExtension]和c#进行网页数据提取:fizzler是HtmlAgilityPack的一个扩展,支持jQuery Selector: 提取数据 ...
- 循序渐进Python3(三) -- 3 -- 内置函数
上一篇我们又介绍了26个Python内置函数.现回忆一下吧: 1.all 2.any 3.ascii 4.bin 5.bool 6.bytes 7.bytearray 8.callable 9.chr ...
- JQuery this 和 $(this) 详解
this this 在面向对象语言中,指代调用上下文对象,在js中,也是一模一样的概念,所以不管这个this出现在什么地方,只要追踪到当前调用对象是什么,那么this是什么也就一目了然了. 先看一个 ...
- 普林斯顿结构 VS 哈佛结构
1. 冯·诺依曼结构 冯·诺依曼结构,又称为普林斯顿体系结构,是一种将程序指令存储器和数据存储器合并在一起的存储器结构.取指令和取操作数都在同一总线上,通过分时复用的方式进行:缺点是在高速运行时,不能 ...
- 第二章 第二个spring-boot程序(转载)
本编博客转发自:http://www.cnblogs.com/java-zhao/p/5336369.html 上一节的代码是spring-boot的入门程序,也是官方文档上的一个程序.这一节会引入s ...
- php匹配中文代码(字符串中包含中文或者全是中文)
<?php$str= "中文";//全部是汉字的$par = "\x80-\xff";$par2= chr(0xa1).'-'.chr(0xff);//包 ...
- Linux命令小结:fdisk
查看分区信息 分区信息包括容量.扇区数目.柱面数目.磁头数目和IO大小等信息. root@cvm:/# fdisk -l /dev/sda7 Disk /dev/sda7: 441.8 GB, 441 ...
- Spring 4 官方文档学习(十一)Web MVC 框架之HTTP caching support
一个良好的HTTP缓存策略可以显著地增进web应用的性能和其客户端的体验.主要使用"Cache-Control" HTTP response header来完成,配合conditi ...