elixir 高可用系列(三) GenEvent

来源:http://www.cnblogs.com/wang_yb/archive/2016/05/25/5521014.html
-Advertisement-
Play Games

概述 GenEvent 是事件處理的通用部分的抽象。 通過 GenEvent ,我們給已有的服務 動態 的添加 事件處理。 GenEevent 和 GenServer 的區別 之前已經介紹了 GenServer ,GenServer 和 GenEvent 的主要區別在於: GenServer 是服務 ...


概述

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/


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • public class MyClass : IDisposable { public int a; public MyClass() { //構造 } public void Dispose() { Dispose(true); ... ...
  • 顯示結果: ID:1 ParentID: 0 TreeLevel: 0 Name:中國ID:2 ParentID: 1 TreeLevel: 1 Name:江西ID:5 ParentID: 2 TreeLevel: 2 Name:南昌ID:6 ParentID: 5 TreeLevel: 3 Nam ...
  • 直接在vs2013里的App_Data目錄創建資料庫,在伺服器資源管理器中查看時報錯: 未能載入包“Microsoft SQL Server Data Tools” 英文: 以下是右擊表的效果。 解決方案: 1.去https://msdn.microsoft.com/zh-cn/dn864412 下 ...
  • 今天在ASP.NET MVC項目中,實現一個小功能,就是記錄瀏覽者客戶端的一些信息。比如瀏覽者的IP,訪問了哪些頁面,以及瀏覽器相關的信息。在資料庫中創建一張表[VisitData]: SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI ...
  • ...
  • 本文是Linux Shell系列教程的第(四)篇,更多shell教程請看:Linux Shell系列教程 與許多的編程語言一樣,Shell中也有註釋符號,今天就為大家來介紹下Shell中的註釋的語法及用法。 Shell中的註釋以“#”號開頭,所有以“#”號開頭的代碼都會被解釋器所忽略。 比如下麵的代 ...
  • 官方文檔給出了兩種Yii2的安裝方式。一種是通過歸檔文件安裝,另一種則是通過composer進行安裝。兩種方式具體有什麼不同呢?我們這裡不討論,安裝完了你自然也就明白了。 相信很多小伙伴想學Yii2,但是大部分都死在了開頭。所謂萬事開頭難,Yii2無疑更好的證實了這一點,還沒開始就先給你一棒槌。 安 ...
  • 利用介面做參數,寫個計算器,能完成+-*/運算 (1)定義一個介面Compute含有一個方法int computer(int n,int m); (2)設計四個類分別實現此介面,完成+-*/運算 (3)設計一個類UseCompute,含有方法:public void useCom(Compute c ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...