daShangDao_centerBook/md/PROJECT_GUIDE.md
2026-02-28 14:27:33 +08:00

16 KiB
Raw Blame History

图书中心系统 - 开发指南

📚 目录


项目概述

图书中心管理系统是一个基于 Go 语言开发的综合性图书信息管理平台,集成 Elasticsearch 搜索引擎、Redis 缓存、MySQL 数据存储,以及多个第三方服务(孔夫子图书网、拼多多等)。

核心功能

  • 📖 图书管理 - 图书信息的增删改查、批量导入导出
  • 🔍 智能搜索 - 基于 Elasticsearch 的全文检索
  • 📊 销量统计 - 多维度销量数据统计与分析
  • 🖼️ 图片管理 - 图书封面图片上传与管理
  • 🔗 第三方集成 - 孔夫子图书网、拼多多 API 集成
  • 📈 数据监控 - SQL 性能监控、健康检查

技术栈

后端框架

  • Gin - HTTP Web 框架
  • GORM - ORM 框架(部分使用)

数据存储

  • MySQL 8.0+ - 主数据库
  • Redis 6.0+ - 缓存与会话存储
  • Elasticsearch 8.x - 搜索引擎

Go 库依赖

require (
    github.com/gin-gonic/gin v1.9.1
    github.com/go-redis/redis/v8 v8.11.5
    github.com/elastic/go-elasticsearch/v8 v8.11.1
    github.com/go-sql-driver/mysql v1.7.1
    github.com/patrickmn/go-cache v2.1.0+incompatible
    github.com/xuri/excelize/v2 v2.8.0
    github.com/gorilla/websocket v1.5.1
    github.com/gin-contrib/cors v1.4.0
)

工具库

  • go-cache - 内存缓存
  • excelize - Excel 文件处理
  • websocket - WebSocket 通信支持

项目结构

centerBook/
├── main.go                    # 主程序入口
├── go.mod / go.sum            # Go 模块依赖
│
├── es/                        # Elasticsearch 模块
│   ├── es_client.go          # ES 客户端封装
│   ├── es_search.go          # ES 搜索服务
│   ├── es_dll.go             # DLL 接口封装(已弃用)
│   ├── es_dll_test.go        # DLL 单元测试
│   └── DLL测试说明.md         # DLL 测试文档
│
├── es_dll/                    # ES DLL 库
│   ├── es.dll                # Windows DLL 文件
│   └── es.md                 # DLL 接口文档
│
├── erp/                       # ERP 模块
│   └── erp_api.go            # ERP API 接口
│
├── image/                     # 图片处理模块
│   └── image.go              # 图片上传与管理
│
├── kongfz/                    # 孔夫子图书网集成
│   └── kongfz.go             # 孔夫子 API 封装
│
├── tail/                      # 第三方服务集成
│   └── tail.go               # Tail API销量数据等
│
├── middleware/                # 中间件
│   └── middleware.go         # 自定义中间件
│
├── health_api.go             # 健康检查 API
├── logging_middleware.go     # 日志中间件
├── pricing.go                # 定价相关功能
├── sql_monitor.go            # SQL 性能监控
├── ip_log.go                 # IP 日志记录
│
├── README.md                 # 项目说明
└── PROJECT_GUIDE.md          # 本文档

环境配置

开发环境要求

  • Go 1.19 或更高版本
  • MySQL 8.0+
  • Redis 6.0+
  • Elasticsearch 8.x (可选)

配置步骤

1. 克隆项目

git clone <repository-url>
cd centerBook

2. 安装依赖

go mod tidy

3. 数据库配置

main.go 中修改数据库连接:

// MySQL 主数据库
targetDSN := "username:password@tcp(host:port)/book_center?charset=utf8mb4&parseTime=True&loc=Local"

// 指数数据库
zhishuDSN := "username:password@tcp(host:port)/zhishu?charset=utf8mb4&parseTime=True&loc=Local"

4. Redis 配置

rdb := redis.NewClient(&redis.Options{
    Addr:     "localhost:6379",
    Password: "", // Redis 密码
    DB:       0,  // 使用默认 DB
})

5. Elasticsearch 配置

esClient, err := elasticsearch.NewDefaultClient()
// 或指定配置
cfg := elasticsearch.Config{
    Addresses: []string{
        "http://localhost:9200",
    },
}
esClient, err := elasticsearch.NewClient(cfg)

6. 运行项目

# 开发模式
go run main.go

# 编译后运行
go build -o centerBook.exe main.go
./centerBook.exe

服务将在 http://localhost:9009 启动


开发指南

代码规范

1. 命名约定

  • 文件名:使用 snake_case,如 es_search.go
  • 包名:使用小写单词,如 es, image, kongfz
  • 函数名:导出函数使用 PascalCase,私有函数使用 camelCase
  • 常量:全大写下划线分隔,如 ESIndex

2. 错误处理

// 推荐:包装错误信息
if err != nil {
    return fmt.Errorf("查询图书失败: %w", err)
}

// 推荐:记录日志并返回
if err != nil {
    log.Printf("[Error] 查询失败: %v", err)
    return nil, err
}

3. 日志规范

// 日志格式:[模块名] 操作描述 | 关键信息
log.Printf("[SearchBookByISBN] 开始查询 | ISBN=%s", isbn)
log.Printf("[SearchBookByISBN] 查询成功 | 书名=%s", book.BookName)
log.Printf("[SearchBookByISBN] 查询失败 | err=%v", err)

添加新功能

1. 创建新模块

# 在项目根目录创建模块目录
mkdir newmodule

# 创建模块文件
touch newmodule/newmodule.go

2. 模块模板

package newmodule

import (
    "log"
    "fmt"
)

// NewModuleService 创建新模块服务
type NewModuleService struct {
    // 依赖项
}

// NewService 初始化服务
func NewService() *NewModuleService {
    return &NewModuleService{}
}

// DoSomething 执行某项操作
func (s *NewModuleService) DoSomething(input string) (string, error) {
    log.Printf("[NewModule] 开始处理 | input=%s", input)

    // 业务逻辑

    return result, nil
}

3. 注册路由

main.go 中添加路由:

// 初始化服务
newModuleSvc := newmodule.NewService()

// 注册路由
r.GET("/api/newmodule/action", func(c *gin.Context) {
    result, err := newModuleSvc.DoSomething(c.Query("input"))
    if err != nil {
        c.JSON(500, gin.H{"error": err.Error()})
        return
    }
    c.JSON(200, gin.H{"data": result})
})

API 文档

基础信息

  • Base URL: http://localhost:9009
  • 数据格式: JSON
  • 字符编码: UTF-8

响应格式

成功响应

{
  "code": 200,
  "message": "success",
  "data": { ... }
}

错误响应

{
  "error": "错误描述",
  "details": "详细错误信息"
}

主要 API 端点

1. 健康检查

GET /health

响应:

{
  "status": "healthy",
  "timestamp": "2025-01-14T10:30:00Z"
}

2. 图书搜索

GET /search/book?keyword=Go语言&page=1&pageSize=10

参数:

  • keyword: 搜索关键词
  • page: 页码从1开始
  • pageSize: 每页数量

响应:

{
  "code": 200,
  "data": {
    "current_page": 1,
    "data": [...],
    "per_page": 10,
    "total": 100
  }
}

3. 根据 ISBN 查询图书

GET /book/isbn?isbn=9787111111111

4. 批量导入图书

POST /books/batch
Content-Type: application/json

{
  "books": [
    {
      "isbn": "9787111111111",
      "book_name": "Go语言编程",
      "author": "作者名",
      ...
    }
  ]
}

更多 API 详情请参考 main.go 中的路由定义。


Elasticsearch 集成

索引结构

索引名称

const ESIndex = "books-from-mysql-v2"

文档结构

type ESBook struct {
    ID              int64                  `json:"id"`
    BookName        FlexibleString         `json:"book_name"`
    BookPic         BookPicObj             `json:"book_pic"`
    BookPicS        BookPicSObj            `json:"book_pic_s"`
    ISBN            string                 `json:"isbn"`
    Author          string                 `json:"author"`
    Publisher       string                 `json:"publisher"`
    PublicationTime string                 `json:"publication_time"`
    FixPrice        float64                `json:"fix_price"`
    // ... 更多字段
}

使用示例

1. 搜索图书

import "centerBook/es"

// 初始化搜索服务
searchSvc := es.NewESSearchService(esClient)

// 关键词搜索
books, err := searchSvc.SearchBooks("Go语言编程")

// 多条件搜索
books, total, err := searchSvc.SearchBooksByConditions(
    map[string]string{
        "author": "张三",
        "publisher": "清华大学出版社",
    },
    1,  // page
    10, // pageSize
)

2. 添加图书到 ES

req := &es.AddBookFullRequest{
    BookName:  "Go语言编程",
    ISBN:      "9787111111111",
    Author:    "作者名",
    Publisher: "出版社",
    // ... 其他字段
}

book, err := searchSvc.AddBookToES(ctx, req)

3. 更新图书信息

updateData := map[string]interface{}{
    "fix_price": 99.00,
    "author":    "新作者名",
}

err := searchSvc.UpdateBookFieldsByISBNHandler(c)

ES DLL 工具

项目提供了 Windows DLL 工具用于直接操作 Elasticsearch实验性功能

测试 DLL

# 查看所有索引
go run test_es_dll.go list

# 创建索引
go run test_es_dll.go create test_index '{"mappings":{"properties":{"title":{"type":"text"}}}}'

# 搜索文档
go run test_es_dll.go search books-from-mysql-v2 '{"query":{"match_all":{}}}'

注意: DLL 功能处于实验阶段,CreateDocument 方法存在已知问题。


第三方服务集成

孔夫子图书网 API

位置: kongfz/kongfz.go

import "centerBook/kongfz"

// 根据 ISBN 获取图书图片和信息
apiBook, err := kongfz.GetBookImageByISBN(
    isbn,
    "CALF_ELEPHANT_PROXY",  // 代理类型
    "1297757178467602432",  // App Key
    "QgQBvP7f",             // App Secret
)

Tail API销量数据

位置: tail/tail.go

import "centerBook/tail"

// 获取在售数量
onSaleCount, err := tail.GetOnSaleCount(isbn)

// 批量检查销量
salesData, err := tail.CheckSales([]string{"isbn1", "isbn2"})

图片上传

位置: image/image.go

import "centerBook/image"

// 下载并上传图书图片
url, err := image.DownloadAndUploadBookImage(
    imageURL,
    isbn,
    "true",      // 是否使用代理
    bookName,
    "true",      // 是否压缩
)

数据库设计

主表book_center

表结构README.md,主要字段说明:

字段名 类型 说明
id BIGINT 主键ID
isbn VARCHAR(30) ISBN唯一
isbn_hash BIGINT ISBN哈希用于分区
book_name VARCHAR(400) 书名
author VARCHAR(400) 作者
publisher VARCHAR(200) 出版社
fix_price INT 定价(单位:分)
day_sale_7 INT 7天销量
day_sale_30 INT 30天销量
total_sale INT 总销量
buy_counts BIGINT 已售数量
sell_counts BIGINT 在售数量

索引设计

-- 主键
PRIMARY KEY (`id`, `isbn_hash`, `isbn`)

-- 唯一索引
UNIQUE KEY `uk_isbn` (`isbn`, `isbn_hash`)

-- 搜索索引
KEY `idx_book_name` (`book_name` (100))
KEY `idx_author` (`author` (50))
KEY `idx_publisher` (`publisher` (50))
KEY `idx_total_sale` (`total_sale`)
KEY `idx_day_sale_7` (`day_sale_7`)
KEY `idx_day_sale_30` (`day_sale_30`)

-- 组合索引
KEY `idx_core_search` (`day_sale_7`, `vio_book`, `book_set`, `onenum_mbooks`, `ill_publisher`, `ill_author`)

分区策略

PARTITION BY HASH (`isbn_hash`) PARTITIONS 10

部署指南

开发环境

# 1. 启动 MySQL
# 2. 启动 Redis
redis-server

# 3. 启动 Elasticsearch可选
# 4. 运行项目
go run main.go

生产环境

使用 Docker

FROM golang:1.19-alpine AS builder
WORKDIR /app
COPY .. .
RUN go mod tidy && go build -o centerBook main.go

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/centerBook .
EXPOSE 9009
CMD ["./centerBook"]

构建和运行

# 构建镜像
docker build -t centerbook:latest .

# 运行容器
docker run -d \
  -p 9009:9009 \
  -e DB_HOST=mysql \
  -e DB_PASSWORD=password \
  -e REDIS_HOST=redis \
  --name centerbook \
  centerbook:latest

Windows 服务部署

# 使用 NSSM 将程序注册为 Windows 服务
nssm install CenterBook "C:\path\to\centerBook.exe"
nssm start CenterBook

常见问题

1. DLL 加载失败

问题: es DLL 不存在

解决方案:

  • 确保 es_dll/es.dll 文件存在
  • 检查文件路径是否正确
  • 确认 DLL 是为 Windows 平台编译的

2. ES 连接失败

问题: 无法连接到 Elasticsearch

解决方案:

// 检查 ES 配置
cfg := elasticsearch.Config{
    Addresses: []string{"http://localhost:9200"},
    Username:  "elastic",
    Password:  "password",
}

3. 数据库连接池耗尽

问题: too many connections

解决方案:

// 调整连接池配置
db.SetMaxOpenConns(150)
db.SetMaxIdleConns(50)
db.SetConnMaxLifetime(30 * time.Minute)

4. Redis 连接超时

问题: redis: connection timeout

解决方案:

rdb := redis.NewClient(&redis.Options{
    Addr:         "localhost:6379",
    Password:     "",
    DB:           0,
    DialTimeout:  10 * time.Second,
    ReadTimeout:  5 * time.Second,
    WriteTimeout: 5 * time.Second,
    PoolSize:     10,
})

性能优化

1. 查询优化

  • 使用 ES 进行全文检索,避免 MySQL LIKE 查询
  • 合理使用 Redis 缓存热点数据
  • 对大表查询使用分页

2. 并发优化

// 使用 goroutine 并发处理
var wg sync.WaitGroup
results := make(chan Result, 10)

for _, isbn := range isbns {
    wg.Add(1)
    go func(isbn string) {
        defer wg.Done()
        result := searchByISBN(isbn)
        results <- result
    }(isbn)
}

go func() {
    wg.Wait()
    close(results)
}()

3. 缓存策略

// 使用 go-cache 做内存缓存
cache := cache.New(5*time.Minute, 10*time.Minute)

// 设置缓存
cache.Set("key", value, cache.DefaultExpiration)

// 获取缓存
if value, found := cache.Get("key"); found {
    return value
}

测试

运行单元测试

# 运行所有测试
go test ./...

# 运行 ES 模块测试
cd es
go test -v

# 运行特定测试
go test -v -run TestSearchBooks

DLL 功能测试

# 运行完整测试
go run test_es_dll.go test

# 测试单个功能
go run test_es_dll.go list
go run test_es_dll.go search books-from-mysql-v2 '{"query":{"match_all":{}}}'

贡献指南

提交代码

  1. Fork 项目
  2. 创建特性分支 (git checkout -b feature/AmazingFeature)
  3. 提交更改 (git commit -m 'Add some AmazingFeature')
  4. 推送到分支 (git push origin feature/AmazingFeature)
  5. 打开 Pull Request

代码审查清单

  • 代码符合项目规范
  • 添加了必要的注释
  • 更新了相关文档
  • 通过了所有测试
  • 没有引入新的警告

联系方式

  • 项目维护者: 开发团队
  • 问题反馈: 请提交 Issue
  • 文档更新: 2025-01-14

附录

A. 相关文档

B. 外部资源

C. 更新日志

v1.0.0 (2025-01-14)

  • 初始版本发布
  • 完成 ES DLL 集成(实验性)
  • 添加完整的项目文档

最后更新: 2025-01-14 文档版本: 1.0.0