第14章:扩展点与插件机制
14.1 扩展点设计
14.1.1 系统扩展点
sfsEdgeStore 设计了多个扩展点,允许在不修改核心代码的情况下扩展功能:
| 扩展点 | 位置 | 说明 |
|---|---|---|
| 数据接收前 | MQTT 消息处理器 | 消息到达后、存储前 |
| 数据存储前 | 数据库写入前 | 数据验证、转换 |
| 数据查询后 | HTTP 响应前 | 查询结果转换、过滤 |
| 监控数据 | 监控模块 | 自定义监控指标 |
| 告警触发 | 告警模块 | 自定义告警规则 |
14.1.2 Hook 接口设计
go
package hooks
type Hook interface {
Name() string
Priority() int
}
type PreMessageHook interface {
Hook
PreProcess(payload []byte) ([]byte, error)
}
type PreStoreHook interface {
Hook
PreStore(records []*map[string]interface{}) ([]*map[string]interface{}, error)
}
type PostQueryHook interface {
Hook
PostQuery(records record.Records) (record.Records, error)
}
type MonitorHook interface {
Hook
OnMetrics(metrics *monitor.Metrics) error
}
type AlertHook interface {
Hook
OnAlert(alert *alert.Alert) error
}
14.2 插件系统
14.2.1 插件加载器
go
package plugin
import (
"plugin"
"sync"
)
type Plugin interface {
Name() string
Version() string
Init() error
Shutdown() error
}
type Manager struct {
plugins map[string]Plugin
mu sync.RWMutex
}
func NewManager() *Manager {
return &Manager{
plugins: make(map[string]Plugin),
}
}
func (m *Manager) LoadPlugin(path string) error {
p, err := plugin.Open(path)
if err != nil {
return err
}
sym, err := p.Lookup("Plugin")
if err != nil {
return err
}
plugin, ok := sym.(Plugin)
if !ok {
return fmt.Errorf("unexpected type from module symbol")
}
if err := plugin.Init(); err != nil {
return err
}
m.mu.Lock()
m.plugins[plugin.Name()] = plugin
m.mu.Unlock()
return nil
}
func (m *Manager) GetPlugin(name string) (Plugin, bool) {
m.mu.RLock()
defer m.mu.RUnlock()
p, ok := m.plugins[name]
return p, ok
}
func (m *Manager) ShutdownAll() {
m.mu.Lock()
defer m.mu.Unlock()
for name, p := range m.plugins {
if err := p.Shutdown(); err != nil {
log.Printf("Error shutting down plugin %s: %v", name, err)
}
delete(m.plugins, name)
}
}
14.2.2 创建插件
go
// 插件示例:myplugin.go
package main
import (
"log"
"sfsEdgeStore/plugin"
"sfsEdgeStore/hooks"
)
type MyPlugin struct{}
func (p *MyPlugin) Name() string {
return "my-plugin"
}
func (p *MyPlugin) Version() string {
return "1.0.0"
}
func (p *MyPlugin) Init() error {
log.Println("My plugin initialized")
hooks.RegisterPreStoreHook(&MyPreStoreHook{})
return nil
}
func (p *MyPlugin) Shutdown() error {
log.Println("My plugin shutdown")
return nil
}
type MyPreStoreHook struct{}
func (h *MyPreStoreHook) Name() string {
return "my-pre-store"
}
func (h *MyPreStoreHook) Priority() int {
return 100
}
func (h *MyPreStoreHook) PreStore(records []*map[string]interface{}) ([]*map[string]interface{}, error) {
log.Printf("PreStore hook called with %d records", len(records))
for _, record := range records {
if processed, ok := (*record)["processed"]; !ok || !processed.(bool) {
(*record)["processed"] = true
(*record)["processed_at"] = time.Now().UnixNano()
}
}
return records, nil
}
var Plugin MyPlugin
14.2.3 编译插件
bash
# 编译为共享库
go build -buildmode=plugin -o myplugin.so myplugin.go
# 在主程序中加载
pluginManager := plugin.NewManager()
err := pluginManager.LoadPlugin("./myplugin.so")
14.3 实战练习
练习 14.1:Hook 开发
开发一个 PreMessageHook,对消息进行解密。
练习 14.2:插件开发
开发一个完整的插件,包含多个 Hook。
练习 14.3:热重载
实现插件的热重载功能。
14.4 本章小结
本章讲解了系统的扩展点和插件机制:
- 系统扩展点设计
- Hook 接口定义
- 插件系统实现
- 如何开发和加载插件
插件机制让系统具有极强的扩展性。
本书版本 :1.0.0
最后更新 :2026-03-08
sfsEdgeStore - 让边缘数据存储更简单!🚀
技术栈 - Go语言、sfsDb与EdgeX Foundry。纯golang工业物联网边缘计算技术栈
项目地址 :GitHub
GitCode 镜像 :GitCode