设为首页 加入收藏

TOP

elixir 高可用系列(二) GenServer(一)
2017-10-09 13:35:02 】 浏览:1890
Tags:elixir 可用 系列 GenServer

概述

如果我们需要管理多个进程,那么,就需要一个专门的 server 来集中监控和控制这些进程的状态,启停等。
OTP 平台中的 GenServer 就是对这个 server 通用部分的抽象。

利用 GenServer 中已经提供的通用操作, 可以很方便的开发出可靠,健壮的程序。
下面首先通过一个示例演示 GenServer 的方便和强大之处,然后再对其进行介绍。

GenServer 示例

这是一个 GenServer 管理多个进程的示例,模拟控制各个进程的启动,停止,以及状态查询。

defmodule ProcessMonitor do
  use GenServer

  #====================================================
  # api for clients
  #====================================================
  # start GenServer
  def start(data, opt \\ []) do
    GenServer.start_link(__MODULE__, data, opt)
  end

  # add process which is controled by this GenServer
  def process_add(server, name) do
    GenServer.call(server, {:add, name})
  end

  # get process status
  def process_status(server, name) do
    GenServer.call(server, {:status, name})
  end

  # start a process by name
  def process_start(server, name) do
    GenServer.cast(server, {:start, name})
  end

  # stop a process by name
  def process_stop(server, name) do
    GenServer.cast(server, {:stop, name})
  end

  #====================================================
  # callbacks for server
  #====================================================
  def init(data) do
    {:ok, data}
  end

  # handle status message synchronization
  def handle_call({:status, name}, _from, data) do
    val = Map.get(data, name, nil)
    {:reply, val, data}
  end

  # handle add message synchronization
  def handle_call({:add, name}, _from, data) do
    data = Map.put(data, name, "stopped")
    {:reply, name, data}
  end

  # handle start message asynchronization
  def handle_cast({:start, name}, data) do
    data = Map.put(data, name, "running")
    {:noreply, data}
  end

  # handle stop message asynchronization
  def handle_cast({:stop, name}, data) do
    data = Map.put(data, name, "stopped")
    {:noreply, data}
  end

end

上面代码测试方法如下:

$ iex -S mix
Erlang/OTP 18 [erts-7.3] [source] [64-bit] [smp:4:4] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Interactive Elixir (1.2.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> {:ok, server} = ProcessMonitor.start(Map.new)               # 创建 GenServer,并初始化一个 map 用于存储此server管理的 process 信息
{:ok, #PID<0.87.0>}
iex(2)> ProcessMonitor.process_status(server, "process01")          # 创建 GenServer 后,默认没有管理任何进程,所以没有 process01 的信息
nil
iex(3)> ProcessMonitor.process_add(server, "process01")             # 给 GenServer 增加一个被管理进程 process01
"process01"
iex(4)> ProcessMonitor.process_status(server, "process01")          # 新加入的进程默认状态是 stopped,示例代码默认这么实现
"stopped"
iex(5)> ProcessMonitor.process_start(server, "process01")           # 启动 process01
:ok
iex(6)> ProcessMonitor.process_status(server, "process01")          # process01 状态变为 running
"running"
iex(7)> ProcessMonitor.process_stop(server, "process01")            # 停止 process01
:ok
iex(8)> ProcessMonitor.process_status(server, "process01")          # process01 状态变为 stopped
"stopped"
iex(9)> ProcessMonitor.process_add(server, "process02")             # 再增加一个被管理进程 process02
"process02"
iex(10)> ProcessMonitor.process_start(server, "process02")          # 启动 process02
:ok
iex(11)> ProcessMonitor.process_status(server, "process02")         # process02 状态变为 running
"running"
iex(12)> ProcessMonitor.process_status(server, "
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇第二章 rabbitmq在mac上的安装 下一篇elixir 高可用系列(三) GenEvent

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目