machine golang 并发工具包使用
以前有简单介绍过machine,以下是一个简单的试用(集成了gorunine 以及cron任务)
项目结构
- 代码结构
├── docker-compose.yaml
├── go.mod
├── go.sum
├── main.go
├── pkg
│ ├── filesync.go
│ └── updatefile.go
└── sql
└── init.sql
- 代码说明
以上是一个简单的基于machine发布订阅以及定时任务能力实现的一个同时数据写入db - main.go
基于machine实现goruntine 的管理,支持PanicRecover,发布订阅以及定时任务
package main
import (
"context"
"demoapp/pkg"
"fmt"
"log"
"net/http"
_ "net/http/pprof"
"time"
"github.com/autom8ter/machine"
_ "github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
func main() {
db, err := sqlx.Connect("mysql", "root:appdemo@tcp(127.0.0.1:3306)/app?charset=utf8")
if err != nil {
log.Fatalln(err)
}
defer db.Close()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
m := machine.New(ctx, machine.WithTags("demoapp"), machine.WithMaxRoutines(10),
machine.WithMiddlewares(machine.PanicRecover()))
m.Go(func(routine machine.Routine) {
fmt.Printf("%v | stats = %s\n", routine.PID(), routine.Machine().Stats().Tags)
// publish message to channel
sameFiles, err := pkg.FetchSameFile(db)
if err != nil {
log.Println("fetch sameFiles error", err.Error())
routine.Publish("demo", err)
}
if len(sameFiles)%2 == 0 {
// normal datas
routine.Publish("demo", sameFiles)
} else {
routine.Publish("demo", map[string]interface{}{
"name": "dlaong",
})
}
// 支持定时任务以及tag 的中间件扩展
}, machine.GoWithTags("publish"),
machine.GoWithPID("demoapp"),
machine.GoWithMiddlewares(
// run every second until context cancels
machine.Cron(time.NewTicker(1*time.Second)),
))
m.Go(func(routine machine.Routine) {
fmt.Printf("one: %v | stats = %s\n", routine.PID(), routine.Machine().Stats().Tags)
// 订阅
routine.Subscribe("demo", func(msg interface{}) {
switch msg.(type) {
case error:
log.Println("print error message")
case []pkg.SameFile:
pkg.Update2(db, msg.([]pkg.SameFile))
default:
log.Println("don't know", msg)
}
})
})
m.Go(func(routine machine.Routine) {
// http seerver 同时进行消息发布
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
routine.Publish("demo", map[string]interface{}{
"name": "dlaong",
"type": "from web server",
})
fmt.Fprintf(w, "%s userinfo", "dalong")
})
http.ListenAndServe(":8080", nil)
})
m.Wait()
}
db 操作,很简单,主要是基于sqlx进行的mysql 操作,参考代码
filesync.go:
package pkg
import "github.com/jmoiron/sqlx"
// User for db user
type User struct {
// UID
UID int `json:"uid" db:"uid"`
}
// SameFile for db SameFile
type SameFile struct {
// UID
Parent int64 `json:"parent" db:"parent"`
Name string `json:"name" db:"name"`
}
// FetchUser fetch users
func FetchUser(con *sqlx.DB) (users []User, err error) {
selectSQL := `select distinct uid from user`
myusers := []User{}
err = con.Select(&myusers, selectSQL)
if err != nil {
return nil, err
}
return myusers, nil
}
// FetchSameFile fetch samefile
func FetchSameFile(con *sqlx.DB) (sameFiles []SameFile, err error) {
selectSQL := `select distinct parent,name from file where size >0 group by parent,name having count(*)>1`
mysameFile := []SameFile{}
err = con.Select(&mysameFile, selectSQL)
if err != nil {
return nil, err
}
return mysameFile, nil
}
updatefile.go
package pkg
import (
"log"
"github.com/jmoiron/sqlx"
)
// Update2 update samefile
func Update2(con *sqlx.DB, sameFiles []SameFile) {
log.Println("fetch same file counts:", len(sameFiles))
for _, SameFile := range sameFiles {
updateSQL := `insert into log2(id,content) values(:id,:content)`
log.Println("name,parent", SameFile.Name, SameFile.Parent)
result, err := con.NamedExec(updateSQL, map[string]interface{}{
"id": SameFile.Parent,
"content": SameFile.Name,
})
if err != nil {
log.Println("some wrong:", err.Error())
}
effectCount, err := result.RowsAffected()
if err != nil {
log.Println("exec wrong:", err.Error())
}
log.Println("exec result:", effectCount)
}
}
- 参考火焰图(结合系统查看)
可以方便分析goruntine
说明
以上代码比较简单,同时也集成了pprof,我们可以观测goruntine的 行为
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
2019-12-24 perf + perf-agent-map+bindfs +flamescope生成java docker 火焰图
2018-12-24 lerna import && add 使用&&常见问题解决
2018-12-24 memsql kafka集成
2017-12-24 testem方便的web tdd 测试框架使用
2015-12-24 ManifoldJS
2015-12-24 Top JavaScript Frameworks, Libraries & Tools and When to Use Them
2014-12-24 CSQuery 简单测试