跳到主要内容

microkernel 设计8

1. 目标

  • 服务热更新增加状态迁移
  • 支持服务加密状态迁移

2. 代码改动

2.1 Kernel(核心)

新增状态接口

// 旧服务可选实现:导出状态
type Exportable interface {
ExportState() any
}

// 新服务可选实现:导入状态
type Importable interface {
ImportState(state any) error
}

加密接口

type Crypter interface {
Encrypt(data any) ([]byte, error)
Decrypt(cipher []byte) (any, error)
}

加密实现

使用aes

type AESCrypter struct {
key []byte // 16/24/32 字节
}

func NewAESCrypter(key []byte) *AESCrypter {
return &AESCrypter{key: key}
}

func (a *AESCrypter) Encrypt(data any) ([]byte, error) {
plaintext, err := json.Marshal(data)
if err != nil {
return nil, err
}
block, err := aes.NewCipher(a.key)
if err != nil {
return nil, err
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}

nonce := make([]byte, aesgcm.NonceSize())
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return nil, err
}

ciphertext := aesgcm.Seal(nonce, nonce, plaintext, nil)
return ciphertext, nil
}

func (a *AESCrypter) Decrypt(ciphertext []byte) (any, error) {
block, err := aes.NewCipher(a.key)
if err != nil {
return nil, err
}
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return nil, err
}

nonceSize := aesgcm.NonceSize()
if len(ciphertext) < nonceSize {
return nil, fmt.Errorf("ciphertext too short")
}

nonce := ciphertext[:nonceSize]
cipherData := ciphertext[nonceSize:]

plaintext, err := aesgcm.Open(nil, nonce, cipherData, nil)
if err != nil {
return nil, err
}

var result any
if err := json.Unmarshal(plaintext, &result); err != nil {
return nil, err
}
return result, nil
}

替换服务

//func (k *MicroKernel) ReplaceService(newSvc Service) error {
// k.mu.Lock()
// defer k.mu.Unlock()
//
// name := newSvc.Name()
// oldMeta, exists := k.services[name]
// var state any
//
// if exists {
// if exporter, ok := oldMeta.svc.(Exportable); ok {
// state = exporter.ExportState()
// }
// oldMeta.svc.Stop()
// fmt.Printf("Stopped old version of %s\n", name)
// }
//
// // 状态迁移
// if importer, ok := newSvc.(Importable); ok && state != nil {
// if err := importer.ImportState(state); err != nil {
// return fmt.Errorf("state import failed: %w\n", err)
// }
// fmt.Printf("State migrated for service %s\n", name)
// }
//
// // 替换服务元信息
// k.services[name] = &serviceMeta{
// svc: newSvc,
// deps: newSvc.Dependencies(),
// state: Created,
// }
//
// // 重启服务
// if exists && oldMeta.state == Running {
// newSvc.Start()
// k.services[name].state = Running
// fmt.Printf("Started new version of %s", name)
// } else {
// fmt.Printf("Registered new version of %s (not started)", name)
// }
//
// return nil
//}

func (k *MicroKernel) ReplaceServiceEncrypted(newSvc Service, crypter Crypter) error {
k.mu.Lock()
defer k.mu.Unlock()

name := newSvc.Name()
oldMeta, exists := k.services[name]
var encryptedState []byte

if exists {
if exporter, ok := oldMeta.svc.(Exportable); ok {
rawState := exporter.ExportState()
cipher, err := crypter.Encrypt(rawState)
if err != nil {
return fmt.Errorf("state encryption failed: %w", err)
}
encryptedState = cipher
}
oldMeta.svc.Stop()
fmt.Printf("Stopped old version of %s\n", name)
}

// 状态导入(解密)
if importer, ok := newSvc.(Importable); ok && encryptedState != nil {
decrypted, err := crypter.Decrypt(encryptedState)
if err != nil {
return fmt.Errorf("state decryption failed: %w", err)
}
if err := importer.ImportState(decrypted); err != nil {
return fmt.Errorf("state import failed: %w", err)
}
fmt.Printf("Encrypted state migrated for service %s\n", name)
}

k.services[name] = &serviceMeta{
svc: newSvc,
deps: newSvc.Dependencies(),
state: Created,
}

if exists && oldMeta.state == Running {
newSvc.Start()
k.services[name].state = Running
fmt.Printf("Started new version of %s\n", name)
} else {
fmt.Printf("Registered new version of %s (not started)\n", name)
}

return nil
}


2.2 echo服务

实现状态接口

func (e *EchoServiceV2) ImportState(state any) error {
if val, ok := state.(int); ok {
e.echoCount = val
return nil
}
return fmt.Errorf("invalid state type")
}
func (e *EchoService) ExportState() any {
return e.echoCount
}

2.3 main

热替换服务

// 7. 热替换服务
// 热更新为 V2
aesKey := []byte("1234567890123456") // 16 字节对称密钥
microKernel.ReplaceServiceEncrypted(service.NewEchoServiceV2(microKernel), microkernel.NewAESCrypter(aesKey))


2.4 运行结果

Registered: logger
Registered: echo
Starting all services...
Services: [echo logger]
[echo] starting...
Started: echo
[logger] starting...
Started: logger
[logger] LOG: Hello, Microkernel!
[MicroKernel] Event from logger: - Hello, Microkernel!
[logger] got reply from kernel: Handled by kernel
[logger] LOG: Hello, Echo!
[MicroKernel] Event from logger: - Hello, Echo!
[logger] got reply from kernel: echo service handled
[MicroKernel] Send Event to echo: Hello, Log!
{0 echo service handled from microKernel: Hello, Log!}
[echo] stopping...
Stopped old version of echo
State migrated for service echo
[2025-04-24 21:28:38.032] [INFO] [echo] [echov2] starting...

Started new version of echo[MicroKernel] Send Event to echo: Hello, Log!
[echo] count is 10
{0 echo v2 service handled from microKernel: Hello, Log!}
[MicroKernel] Event from main: - log
v2 reply: {0 Handled by kernel ok}
Stopping all services...
[logger] stopping...
Stopped: logger
[echov2] stopping...
Stopped: echo
[log] stopping

查看完整代码