Go routine 编排框架:oklog/run 包
Go routine 编排框架:oklog/run 包
问题引入
oklog/run 包提供了一套非常简单、易用的 Go routine 编排框架。在介绍 oklog/run 前,我们先考虑以下问题:
假设我们有四个 Go routine 组件,如图所示,分别是运行一个状态机 sm.Run 、启动一个 HTTP 服务器、执行定时任务 cronJobs(sm) 读取状态机状态、和运行信号监听器。每个 Go routine 组件互相独立运行。
问题在于,我们如何将各个组件作为一个整体运行,并有序地结束?

对于每一个 Go routine 组件,我们都有相应的办法来执行结束操作。状态机通过 Context 对象,HTTP 服务器通过调用 Listener 的 Close 方法,定时任务和监听器通过 channel。当一个组件结束的时候,需要通知其他组件有序执行结束操作。这个问题的解决方法可以用 Actor 模型来描述。每个 Go routine 都是一个 actor,互相独立,互相之间只能通过 message 通信。oklog/run 包实现了 Actor 模型,能非常简洁的实现 Go routine 编排功能。

oklog/run 包介绍
oklog/run 包非常简单,只有一个类型,两个方法,共 60 行代码。其中 Group 是一组 actor,通过调用 Add 方法将 actor 添加到 Group 中。
type Group
func (g *Group) Add(execute func() error, interrupt func(error))
func (g *Group) Run() error
type Group struct {
actors []actor
}
func (g *Group) Add(execute func() error, interrupt func(error)) {
g.actors = append(g.actors, actor{execute, interrupt})
}
每个 actor 有两个方法:execute 和 interrupt。execute 完成 Go routine 的计算任务,interrupt 结束 Go routine 并退出。
type actor struct {
execute func() error
interrupt func(error)
}
调用 Run 方法后会启动所有 Go routine(或者称为 actor),并等待第一个结束的 Go routine(无论正常退出或因为异常终止)。一旦捕获到第一个结束信号,会依次结束其他 Go routine 直到所有 Go routine 完全退出。
func (g *Group) Run() error {
if len(g.actors) == 0 {
return nil
}
// Run each actor.
errors := make(chan error, len(g.actors))
for _, a := range g.actors {
go func(a actor) {
errors <- a.execute()
}(a)
}
// Wait for the first actor to stop.
err := <-errors
// Signal all actors to stop.
for _, a := range g.actors {
a.interrupt(err)
}
// Wait for all actors to stop.
for i := 1; i < cap(errors); i++ {
<-errors
}
// Return the original error.
return err
}
使用例子
下面例子定义了三个 actor,前两个 actor 一直等待。第三个 actor 在 3s 后结束退出。引起前两个 actor 退出。
package main
import (
"fmt"
"github.com/oklog/run"
"time"
)
func main() {
g := run.Group{}
{
cancel := make(chan struct{})
g.Add(
func() error {
select {
case <- cancel:
fmt.Println("Go routine 1 is closed")
break
}
return nil
},
func(error) {
close(cancel)
},
)
}
{
cancel := make(chan struct{})
g.Add(
func() error {
select {
case <- cancel:
fmt.Println("Go routine 2 is closed")
break
}
return nil
},
func(error) {
close(cancel)
},
)
}
{
g.Add(
func() error {
for i := 0; i <= 3; i++ {
time.Sleep(1 * time.Second)
fmt.Println("Go routine 3 is sleeping...")
}
fmt.Println("Go routine 3 is closed")
return nil
},
func(error) {
return
},
)
}
g.Run()
}
打印结果:
Go routine 3 is sleeping...
Go routine 3 is sleeping...
Go routine 3 is sleeping...
Go routine 3 is closed
Go routine 2 is closed
Go routine 1 is closed
参考资料
Ways To Do Things - Peter Bourgon
Go routine 编排框架:oklog/run 包的更多相关文章
- Spring 框架的架包分析、功能作用、优点,及jar架包简介
Spring 框架的架包详解 Spring的作用 Spring的优势 由于刚搭建完一个MVC框架,决定分享一下我搭建过程中学习到的一些东西.我觉得不管你是个初级程序员还是高级程序员抑或 ...
- SSH框架整合jar包时的注意事项
SSH框架整合jar包时的注意事项: 在将三个框架所需的jar整合到一起后,要看一下有没有相同类型但是版本不同的jar包,如果有的话,需要把低版本的jar包删除掉,否则会报错.我这里整合的时候java ...
- 初识 Knative: 跨平台的 Serverless 编排框架
Knative 是什么 Knative 是 Google 在 2018 的 Google Cloud Next 大会上发布的一款基于 Kubernetes 的 Serverless 框架.Knativ ...
- Spring MVC 框架的架包分析,功能作用,优点
由于刚搭建完一个MVC框架,决定分享一下我搭建过程中学习到的一些东西.我觉得不管你是个初级程序员还是高级程序员抑或是软件架构师,在学习和了解一个框架的时候,首先都应该知道的是这个框架的原理和与其有关j ...
- Python基于Flask框架配置依赖包信息的项目迁移部署小技巧
一般在本机上完成基于Flask框架的代码编写后,如果有接口或者数据操作方面需求需要把代码部署到指定服务器上. 一般情况下,使用Flask框架开发者大多数都是选择Python虚拟环境来运行项目,不同的虚 ...
- 手把手安装Laravel框架(permissions扩展包)实现RBAC权限---以及一些安装时的ERROR
a.依赖管理工具,框架,环境 1.composer 2.laravel(我的是5.5) 3.PHP(我的7.2),MySql(我的5.7) b,安装 1.首先需要安装一个干净的 Laravel 项目, ...
- Struts2+Hibernate+Spring(SSH)三大框架整合jar包
Struts2 + Spring3 + Hibernate3 框架整合 1. 每个框架使用 (开发环境搭建 )* 表现层框架 struts2 1) jar包导入: apps/struts2_blank ...
- c#基于事件模型的UDP通讯框架(适用于网络包编解码)
之前写过一篇关于c#udp分包发送的文章 这篇文章里面介绍的方法是一种实现,可是存在一个缺点就是一个对象序列化后会增大非常多.不利于在网络中的传输. 我们在网络中的传输是须要尽可能的减小传送的数据包的 ...
- Gin-Go学习笔记八:Gin-Web框架 常用的包
常用的包 1> 在java,.net,php,node.js等语言常常会使用到包的概念.包的使用,可以加快项目的进度的开发,以及更好的实现项目的效果.我在网上查到了包的作用如下: 1.包 ...
随机推荐
- 手把手告诉你如何安装多个版本的node,妈妈再也不用担心版本高低引发的一系列后遗症(非常详细,非常实用)
简介 最近好多人都问到node怎么同时安装多个版本? 如何配置node的环境变量,如何自如的在多个版本中切换node?还有就是自己在做appium自动化的时候,有时候会因为node的版本过高或者是太低 ...
- I don't Blame You that You don't Understand Me
I don't Blame You that You don't Understand Me Every one has a dead corner in himself, with no entry ...
- 漏洞复现:MS17-010缓冲区溢出漏洞(永恒之蓝)
MS17-010缓冲区溢出漏洞复现 攻击机:Kali Linux 靶机:Windows7和2008 1.打开攻击机Kali Linux,msf更新到最新版本(现有版本5.x),更新命令:apt-get ...
- Alodi:为了保密我开发了一个系统
每天都在愉快的造轮子,这次可以一键创建测试环境 咖啡君维护了几十个不同类型项目,其中有相当一部分项目是对保密性有很高要求的,也就是说下个版本要上线的内容是不能提前泄露的,就像苹果新产品的介绍网站决不允 ...
- 使用HTML制作网页
网页基本信息[编码格式] gb2312:简体中文,一般用于包含中文和英文的页面 ISO-885901:纯英文,一般用于只包含英文的页面 big5:繁体中文,一般用户带有繁体字的页面 utf-8:国际通 ...
- HBase 超详细介绍
1-HBase的安装 HBase是什么? HBase是Apache Hadoop中的一个子项目,Hbase依托于Hadoop的HDFS作为最基本存储基础单元,通过使用hadoop的DFS工具就可以看到 ...
- 大数据平台搭建 - cdh5.11.1 - spark源码编译及集群搭建
一.spark简介 Apache Spark 是专为大规模数据处理而设计的快速通用的计算引擎,Spark 是一种与 hadoop 相似的开源集群计算环境,但是两者之间还存在一些不同之处,这些有用的不同 ...
- net core WebApi——缓存神器Redis
目录 前言 Redis 使用 RedisUtil 测试 小结 @ 前言 中秋过完不知不觉都已经快两周没动这个工程了,最近业务需要总算开始搞后台云服务了,果断直接net core搞起,在做的中间遇到了不 ...
- React + TypeScript 默认 Props 的处理
React 中的默认 Props 通过组件的 defaultProps 属性可为其 Props 指定默认值. 以下示例来自 React 官方文档 - Default Prop Values: clas ...
- jenkins导致磁盘占满问题
背景 今天登陆jenkins提示磁盘空间不足,且构建发生错误 排查问题 cd到jenkins 安装目录 执行df -h 发现root目录沾满 执行 du -ah --max-depth=1 发现是.j ...