博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
elixir 高可用系列(三) GenEvent
阅读量:6963 次
发布时间:2019-06-27

本文共 2882 字,大约阅读时间需要 9 分钟。

概述

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} endend

测试过程:

# 启动一个空的事件管理器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)>niliex(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:okiex(6)> GenEvent.sync_notify(manager, :world):hello:okiex(7)> GenEvent.sync_notify(manager, :test)"error msg":ok

可以看出,我们没有给 GenEvent 绑定任何的 handler,而是在 GenEvent 的事件流中对所有消息进行了处理。

GenEvent 中事件流的特性是 erlang 中所没有的。

总结

除了上面用的 handle_event 和 stream, GenEvent 中还有其他的实用的 Functios 和 Callbacks

具体参见:

来源:

本文转自wang_yb博客园博客,原文链接:http://www.cnblogs.com/wang_yb/p/5521014.html,如需转载请自行联系原作者

你可能感兴趣的文章
基于jQuery/CSS3实现拼图效果的相册插件
查看>>
【问题解决】小数点前面不显示0的问题
查看>>
ios学习笔记(二)第一个应用程序--Hello World
查看>>
Maven学习总结(四)——Maven核心概念——转载
查看>>
怎么用CIFilter给图片加上各种各样的滤镜_2
查看>>
android:关于主工程和library project
查看>>
CodeForces 2A Winner
查看>>
Window环境配置Mongodb
查看>>
制作和unity调用动态链接库dll文件
查看>>
exsi6.0远程修改密码
查看>>
Header和Cookie相关内容
查看>>
20个可能你不知道Linux网路工具
查看>>
Android 关于listView 显示不全的问题
查看>>
构造函数创建私有变量(防继承)
查看>>
scrum 开发方式学习笔记
查看>>
Terraform使用案例
查看>>
Mac下brew方式安装mysql
查看>>
开源的任务队列服务HTQ
查看>>
通过微信小程序看前端
查看>>
[LeetCode] Rotate Function
查看>>