服务设计
如图所示,热搜服务(Trend Service)从消息队列消费”search book“事件,分析数据并列出热门图书给用户。
热搜服务应该至少包含2个组件:
- 消费者: 负责消费并分析队列中的事件。
- API服务器: 负责向用户展示热搜。
本教程中有 3 个服务,但我们没必要整 3 个仓库。既然都是 Go 开发的,可以尝试一下单仓(monorepo)。
单仓 Monorepo
单仓即”单体仓库“(monolithic repository),是一种将多个项目或系统模块存放在一个仓库内的软件开发方式。
我们需要重整一下项目结构:
.
├── LICENSE
├── README.md
├── domain
│ └── model
│ └── book.go
├── go.mod
├── go.sum
├── infrastructure
│ ├── mq
│ │ ├── helper.go
│ │ └── kafka.go
│ └── parser
│ └── parse.go
└── service
├── recommendation
│ └── main.go
├── trend
│ └── main.go
└── web
├── adapter
│ ├── router.go
│ └── templates
│ └── index.html
├── application
│ ├── executor
│ │ └── book_operator.go
│ └── wire_helper.go
├── config.yml
├── domain
│ └── gateway
│ └── book_manager.go
├── infrastructure
│ ├── config
│ │ └── config.go
│ └── database
│ └── mysql.go
└── main.go
重组目录结构
- 移动 adapter/,application/,domain/gateway/,infrastructure/database/ 和 infrastructure/config/ 目录到 service/web/。
- 移动 main.go 和 config.yml 文件到 service/web/。
- 删除
Parse
函数,infrastructure/config/config.go。
创建 infrastructure/parser/parse.go:
/*
Package parser provides config parse funcs.
*/
package parser
import (
"fmt"
"os"
"gopkg.in/yaml.v3"
)
// Parse parses config file and returns a Config.
func Parse[T any](filename string) (*T, error) {
var c T
buf, err := os.ReadFile(filename)
if err != nil {
return &c, err
}
err = yaml.Unmarshal(buf, &c)
if err != nil {
return &c, fmt.Errorf("failed to parse file %s: %v", filename, err)
}
return &c, nil
}
T
是泛型,可以用于解析任意结构的服务配置文件。