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, "process01") # process01 状态仍然是 stopped,不受 process02 的影响
"stopped"
iex(13)> ProcessMonitor.stop(server) # 停止 GenServer
注 上面的代码是用 mix 创建工程来运行的,mix 的使用方法可以参见 blog:mix 构建工具
GenServer 通用抽象简介
示例代码使用了 GenServer 中的几个关键函数: init handle_call handle_case
- init: 这个函数在 GenServer.start_link 时执行,对 start_link 中的参数进行处理
- handle_call: 这个函数接受同步消息并处理
- handle_cast: 这个函数接受异步消息并处理
处理这3个常用的函数之外,GenServer 中的函数也不是很多,其他的函数,属性以及每个函数返回的值说明请参见:http://elixir-lang.org/docs/stable/elixir/GenServer.html
在上面的示例中,其实 client 也可以直接调用 GenServer 的 handle_call/handle_cast 来发送同步/异步消息,
我之所以封装了一些 api 给 client 调用,一方面,是为了简化客户端的调用(client 的 api 中参数更加简洁直观),
另一方面,将处理消息的代码和 发送消息的代码分开,便于以后扩展(因为,可能存在多个发送消息的处理都对应同一个消息处理)。
elixir 高可用系列(二) GenServer的更多相关文章
- 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 高可用系列(三) GenEvent
概述 GenEvent 是事件处理的通用部分的抽象. 通过 GenEvent ,我们给已有的服务 动态 的添加 事件处理. GenEevent 和 GenServer 的区别 之前已经介绍了 GenS ...
- elixir 高可用系列(一) Agent
概述 elixir 本身是一种 immutable 的语言,默认情况下,进程间是不共享任何状态的,进程之间通过消息来交互. 而 Agent 则封装了一种进程间共享状态的方式,通过这种方式,不用显式的写 ...
- MySQL高可用系列之MHA(二)
一.參数说明 MHA提供了一系列配置參数.深入理解每一个參数的详细含义,对优化配置.合理使用MHA非常重要.非常多高可用性也都是通过合理配置一些參数而实现的. MHA包含例如以下配置參数,分别说明例如 ...
- (5.8)mysql高可用系列——MySQL中的GTID复制(实践篇)
一.基于GTID的异步复制(一主一从)无数据/少数据搭建 二.基于GTID的无损半同步复制(一主一从)(mysql5.7)基于大数据量的初始化 正文: [0]概念 [0.5]GTID 复制(mysql ...
- Mycat高可用解决方案二(主从复制)
Mycat高可用解决方案二(主从复制) 系统部署规划 名称 IP 主机名称 用户名/密码 配置 mysql主节点 192.168.199.110 mysql-01 root/hadoop 2核/2G ...
- Docker 搭建pxc集群 + haproxy + keepalived 高可用(二)
上一节我们有了两个分片的pxc集群,这一节我们接着安装haproxy和keepalived的实现集群的高可用 一.先下载haproxy的镜像 [root@localhost ~]# docker pu ...
随机推荐
- leetcode 141
141. Linked List Cycle Given a linked list, determine if it has a cycle in it. Follow up:Can you sol ...
- sqlserver同步后在不重新初始化快照的情况下新增表
在已有事务复制中,时长需要新增表.索引,这些变更时不会同步到从库中.如果采用默认的设置,每次都需要重新初始化快照,从库重新应用快照和未执行的同步命令,这显然是无法在线上实践的方法.另一种 ...
- 在HttpClient请求的时候,返回结果解析时出现java.io.IOException: Attempted read from closed stream. 异常,解决
原因是EntityUtils.toString(HttpEntity)方法被使用了多次.所以每个方法内只能使用一次.
- ftp服务器远程拷贝命令
xiamense@xiamense-testserver:~$ ftp 218.5.82.40 输入账户密码 get 远程文件路径 本机服务器路径get pa20160927.xml /home/xi ...
- KMeans的图像压缩
# -*- coding: utf-8 -*- """ Created on Thu Aug 11 18:54:12 2016 @author: Administrato ...
- xtrabackup备份与恢复实践
说明 xtrabackup --percona 特点: 开源,在线备份innodb表 支持限速备份,避免对业务造成影响 支持流备 支持增量备份 支持备份文件压缩与加密 支持并行备份与恢复,速度快 ...
- Flume NG简介及配置
Flume下载地址:http://apache.fayea.com/flume/ 常用的分布式日志收集系统: Apache Flume. Facebook Scribe. Apache Chukwa ...
- 8.11 CSS知识点4
边框样式 1.边框宽度 border-width:medium | thin | thick | length border-top-width 设置上边框宽度 border-bottom-widt ...
- [珠玑之椟]浅谈代码正确性:循环不变式、断言、debug
这个主题和代码的实际写作有关,而且内容和用法相互交织,以下只是对于其内容的一个划分.<编程珠玑>上只用了两个章节20页左右的篇幅介绍,如果希望能获得更多的实例和技巧,我比较推崇<程序 ...
- Android菜鸟成长记4-button点击事件
Button 1.button按钮的创建 一般来说,在我们新建一个Android项目的时候,会有会默认有一个activity_main.xml的文件 如果你在新建项目的时候,把Create Activ ...