Command Dispatcher / Command Bus

Command Dispatcher(命令分发器)和 Command Bus(命令总线)是架构模式,属于应用层架构设计的范畴,不在 GoF 23 种设计模式之列。 注意:“Command Dispatcher” 是开发者社区的口语化称呼,没有权威模式书籍正式定义。对应的正式模式名是 EIP(企业集成模式)中的 Content-Based Router(见下文)。 两者不是同一个模式,Command Bus 是在 Content-Based Router 基础上增加了中间件管道的演化版本,核心差异在于中间件管道。 Command Dispatcher Command Bus 核心机制 ID → Handler 直接路由 ID → 中间件链 → Handler 中间件支持 无 有(日志、验证、事务等) 复杂度 简单 较复杂 典型场景 IoT 协议解析、游戏指令 CQRS、DDD 应用层 Command Dispatcher 核心结构: 收到消息 → 解析 ID → registry.get(id) → handler.Handle(data) 服务初始化时将每种指令的处理类注册到一个 Map。运行时收到消息后,解析出消息类型 ID,从注册表查找对应处理器并直接调用。 // Handler 接口,每种指令实现一个 type Handler interface { Handle(data []byte) error } // Dispatcher 维护 id -> handler 的注册表 type Dispatcher struct { handlers map[uint8]Handler } func NewDispatcher() *Dispatcher { return &Dispatcher{handlers: make(map[uint8]Handler)} } func (d *Dispatcher) Register(id uint8, h Handler) { d.handlers[id] = h } func (d *Dispatcher) Dispatch(id uint8, data []byte) error { h, ok := d.handlers[id] if !ok { return fmt.Errorf("unknown command id: 0x%02X", id) } return h.Handle(data) } // --- 具体指令处理类 --- type LoginHandler struct{} func (h *LoginHandler) Handle(data []byte) error { fmt.Printf("处理登录指令: %x\n", data) return nil } type LocationReportHandler struct{} func (h *LocationReportHandler) Handle(data []byte) error { fmt.Printf("处理位置上报: %x\n", data) return nil } // --- 初始化注册 --- func main() { d := NewDispatcher() d.Register(0x01, &LoginHandler{}) d.Register(0x02, &LocationReportHandler{}) // 收到一条原始消息,解析出 id=0x02 d.Dispatch(0x02, []byte{0x01, 0x02, 0x03}) } Command Bus 在 Dispatcher 的基础上增加了中间件管道,每条命令在到达 Handler 之前会依次经过所有中间件。 ...

2026-04-28 · 3 min · 574 words · -

golang kafka

golang kafka https://github.com/Shopify/sarama https://github.com/bsm/sarama-cluster

2019-05-10 · 1 min · 4 words · -

golang flag 获取命令行参数

golang flag 获取命令行参数 flag.String("port", ":8080", "http listen port") 像flag.Int、flag.Bool、flag.String这样的函数格式都是一样的,第一个参数表示参数名称,第二个参数表示默认值,第三个参数表示使用说明和描述。flag.StringVar这样的函数第一个参数换成了变量地址,后面的参数和flag.String是一样的。 flag.Parse() 解析函数将会在碰到第一个非 flag 命令行参数时停止,非flag命令行参数是指不满足命令行语法的参数,如命令行参数为cmd -flag=true abc 则第一个非 flag 命令行参数为 “abc” 使用flag来操作命令行参数,支持的格式如下: -id=1 --id=1 -id 1 --id 1 package main import ( "flag" "fmt" ) func main() { ok := flag.Bool("ok", false, "is ok") id := flag.Int("id", 0, "id") port := flag.String("port", ":8080", "http listen port") var name string flag.StringVar(&name, "name", "123", "name") flag.Parse() fmt.Println("ok:", *ok) fmt.Println("id:", *id) fmt.Println("port:", *port) fmt.Println("name:", name) } 还是非常方便的。 ...

2016-07-01 · 1 min · 106 words · -

golang tcp socket

golang tcp socket Golang的主要 设计目标之一就是面向大规模后端服务程序,网络通信这块是服务端 程序必不可少也是至关重要的一部分。在日常应用中,我们也可以看到Go中的net以及其subdirectories下的包均是"高频+刚需",而TCP socket则是网络编程的主流,即便您没有直接使用到net中有关TCP Socket方面的接口,但net/http总是用到了吧,http底层依旧是用tcp socket实现的。 网络编程方面,我们最常用的就是tcp socket编程了,在posix标准出来后,socket在各大主流OS平台上都得到了很好的支持。关于tcp programming,最好的资料莫过于W. Richard Stevens 的网络编程圣经《UNIX网络 编程 卷1: socket 联网API》 了,书中关于tcp socket接口的各种使用、行为模式、异常处理讲解的十分细致。Go是自带runtime的跨平台编程语言,Go中暴露给语言使用者的tcp socket api是建立OS原生tcp socket接口之上的。由于Go runtime调度的需要,golang tcp socket接口在行为特点与异常处理方面与OS原生接口有着一些差别。这篇博文的目标就是整理出关于Go tcp socket在各个场景下的使用方法、行为特点以及注意事项。 模型 从tcp socket 诞生后, 网络编程架构模型也几经演化, 大致是: “每进程一个连接” –> “每线程一个连接” –> “Non-Block + I/O多路复用 (linux epoll/windows iocp/freebsd darwin kqueue/solaris Event Port)"。伴随着模型的演化,服务程序愈加强大,可以支持更多的连接,获得更好的处理性能。 目前主流web server一般均采用的都是"Non-Block + I/O多路复用” (有的也结合了多线程、多进程) 。不过I/O多路复用也给使用者带来了不小的复杂度,以至于后续出现了许多高性能的I/O多路复用框架, 比如libevent、libev、libuv等,以帮助开发者简化开发复杂性,降低心智负担。不过Go的设计者似乎认为I/O多路复用的这种通过回调机制割裂控制流的方式依旧复杂,且有悖于"一般逻辑"设计,为此Go语言将该"复杂性"隐藏在Runtime中了: Go开发者无需关注socket是否是 non-block的,也无需亲自注册文件描述符的回调,只需在每个连接对应的goroutine中以"block I/O"的方式对待socket处理即可,这可以说大大降低了开发人员的心智负担。一个典型的Go server端程序大致如下: //go-tcpsock/server.go func handleConn(c net.Conn) { defer c.Close() for { // read from the connection ...

2016-06-29 · 11 min · 2233 words · -