文档章节

elixir 高可用系列(三) GenEvent

linuxr
 linuxr
发布于 2017/01/29 16:38
字数 863
阅读 10
收藏 0

概述

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/

© 著作权归作者所有

linuxr
粉丝 3
博文 12
码字总数 12658
作品 0
南京
后端工程师
私信 提问
Elixir 1.0 正式版发布,函数式编程语言

下载: https://github.com/elixir-lang/elixir/releases/tag/v1.0.0 更新 Enhancements [Logger] Add Logger.enable/1 and Logger.disable/1 Backwards incompatible changes [GenEvent] N......

ifsc01
2014/09/11
26
0
elixir官方教程Mix与OTP(二) 代理

代理 状态问题 代理 ExUnit回调 其它代理动作 代理中的客户端/服务器 本章我们将创建一个名为的模块.这个模块的作用是以一种可以被其它进程读取和修改的方式存储我们的键值对. 如果你跳过了入...

ljzn
2016/08/10
186
0
Phoenix官方教程 (三) 路由

router是Phoenix应用的中心。它们将匹配HTTP请求匹配到控制器动作,接通实时频道管理,并为作用域中间件定义了一系列的管道变换来设置route。 Phoenix生成的router文件, 看上去会是这样: ...

ljzn
2016/08/16
229
0
总有你要的编程书单(GitHub )

目录 IDE IntelliJ IDEA 简体中文专题教程 MySQL 21分钟MySQL入门教程 MySQL索引背后的数据结构及算法原理 NoSQL Disque 使用教程 Neo4j .rb 中文資源 Redis 命令参考 Redis 设计与实现 The ...

汇智网
2017/11/22
0
0
ActiveMQ从入门到精通(三)

这是ActiveMQ系列的最后一篇文章,主要是关于ActiveMQ集群,这里采用的方式是:Zookeeper+LevelDB+ActiveMQ。前面2篇博客地址如下:《ActiveMQ从入门到精通(一)》、《ActiveMQ从入门到精通...

zfz_linux_boy
2017/03/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Android面试常客之Handler全解

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/fnhfire_7030/article/details/79518819 前言:又到了一年...

shzwork
18分钟前
4
0
position sticky 定位

本文转载于:专业的前端网站➫position sticky 定位 1、兼容性 https://caniuse.com/#search=sticky chrome、ios和firefox兼容性良好。 2、使用场景 sticky:粘性。粘性布局。 在屏幕范围内时...

前端老手
25分钟前
3
0
CentOS 7 yum 安装 PHP7.3 教程

参考:https://www.mf8.biz/centos-rhel-install-php7-3/ 1、首先安装 EPEL 源: yum install epel-release 安装 REMI 源: yum install http://rpms.remirepo.net/enterprise/remi-release......

dragon_tech
39分钟前
4
0
Linux物理网卡聚合及桥接

Linux内部实现的bridge可以把一台机器上的多张网卡桥接起来,从而把自己作为一台交换机。同时,LInux bridge还支持虚拟端口,即桥接的不一定都是物理网卡接口,还可以是虚拟接口。目前主要表...

xiangyunyan
40分钟前
4
0
一起来学Java8(一)——函数式编程

在这篇文章中,我们将了解到在Java8下如何进行函数式编程。 函数式编程 所谓的函数式编程就是把函数名字当做值进行传递,然后接收方拿到这个函数名进行调用。 首先来看下JavaScript如何进行函...

猿敲月下码
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部