9.1 Caddy架构深入理解

9.1.1 模块化架构

Caddy采用高度模块化的架构设计,所有功能都以模块形式实现。

核心组件: - App模块:HTTP、TLS、PKI等应用 - Handler模块:处理HTTP请求的中间件 - Matcher模块:请求匹配器 - Provider模块:DNS、存储等提供商

// 模块接口定义
type Module interface {
    CaddyModule() ModuleInfo
}

type ModuleInfo struct {
    ID  ModuleID
    New func() Module
}

// 示例模块实现
type MyModule struct {
    Field string `json:"field,omitempty"`
}

func (MyModule) CaddyModule() caddy.ModuleInfo {
    return caddy.ModuleInfo{
        ID:  "http.handlers.my_module",
        New: func() caddy.Module { return new(MyModule) },
    }
}

9.1.2 请求处理流程

// HTTP请求处理流程
type Server struct {
    Listen   []string `json:"listen,omitempty"`
    Routes   RouteList `json:"routes,omitempty"`
    Errors   *HTTPErrorConfig `json:"errors,omitempty"`
    TLSConnPolicies caddytls.ConnectionPolicies `json:"tls_connection_policies,omitempty"`
}

// 路由匹配和处理
type Route struct {
    Group      string          `json:"group,omitempty"`
    Match      MatcherSets     `json:"match,omitempty"`
    Handle     HandlerModules  `json:"handle,omitempty"`
    Terminal   bool           `json:"terminal,omitempty"`
}

9.1.3 中间件链

// 中间件接口
type MiddlewareHandler interface {
    ServeHTTP(http.ResponseWriter, *http.Request, Handler) error
}

// Handler接口
type Handler interface {
    ServeHTTP(http.ResponseWriter, *http.Request) error
}

// 中间件链构建
func buildMiddlewareChain(handlers []MiddlewareHandler, finalHandler Handler) Handler {
    if len(handlers) == 0 {
        return finalHandler
    }
    
    return HandlerFunc(func(w http.ResponseWriter, r *http.Request) error {
        return handlers[0].ServeHTTP(w, r, buildMiddlewareChain(handlers[1:], finalHandler))
    })
}

9.2 自定义中间件开发

9.2.1 基础中间件结构

package mymiddleware

import (
    "context"
    "fmt"
    "net/http"
    "time"
    
    "github.com/caddyserver/caddy/v2"
    "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
    "github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
    "github.com/caddyserver/caddy/v2/modules/caddyhttp"
    "go.uber.org/zap"
)

func init() {
    caddy.RegisterModule(Middleware{})
    httpcaddyfile.RegisterHandlerDirective("my_middleware", parseCaddyfile)
}

// Middleware 自定义中间件
type Middleware struct {
    Message string `json:"message,omitempty"`
    Delay   caddy.Duration `json:"delay,omitempty"`
    logger  *zap.Logger
}

// CaddyModule 返回模块信息
func (Middleware) CaddyModule() caddy.ModuleInfo {
    return caddy.ModuleInfo{
        ID:  "http.handlers.my_middleware",
        New: func() caddy.Module { return new(Middleware) },
    }
}

// Provision 初始化模块
func (m *Middleware) Provision(ctx caddy.Context) error {
    m.logger = ctx.Logger(m)
    return nil
}

// Validate 验证配置
func (m *Middleware) Validate() error {
    if m.Message == "" {
        return fmt.Errorf("message cannot be empty")
    }
    return nil
}

// ServeHTTP 处理HTTP请求
func (m Middleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
    // 记录请求开始
    start := time.Now()
    m.logger.Info("request started",
        zap.String("method", r.Method),
        zap.String("path", r.URL.Path),
        zap.String("remote_addr", r.RemoteAddr),
    )
    
    // 添加自定义头部
    w.Header().Set("X-Custom-Message", m.Message)
    
    // 模拟延迟
    if m.Delay > 0 {
        time.Sleep(time.Duration(m.Delay))
    }
    
    // 调用下一个处理器
    err := next.ServeHTTP(w, r)
    
    // 记录请求完成
    duration := time.Since(start)
    m.logger.Info("request completed",
        zap.Duration("duration", duration),
        zap.Int("status", w.(*caddyhttp.ResponseRecorder).Status()),
    )
    
    return err
}

// parseCaddyfile 解析Caddyfile配置
func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) {
    var m Middleware
    
    for h.Next() {
        for h.NextBlock(0) {
            switch h.Val() {
            case "message":
                if !h.Args(&m.Message) {
                    return nil, h.ArgErr()
                }
            case "delay":
                var delayStr string
                if !h.Args(&delayStr) {
                    return nil, h.ArgErr()
                }
                delay, err := time.ParseDuration(delayStr)
                if err != nil {
                    return nil, h.Errf("invalid delay duration: %v", err)
                }
                m.Delay = caddy.Duration(delay)
            default:
                return nil, h.Errf("unrecognized subdirective: %s", h.Val())
            }
        }
    }
    
    return m, nil
}

// Interface guards
var (
    _ caddy.Provisioner           = (*Middleware)(nil)
    _ caddy.Validator            = (*Middleware)(nil)
    _ caddyhttp.MiddlewareHandler = (*Middleware)(nil)
    _ caddyfile.Unmarshaler      = (*Middleware)(nil)
)

9.2.2 高级中间件功能

// 带状态的中间件
type StatefulMiddleware struct {
    Config   string `json:"config,omitempty"`
    counter  int64
    mutex    sync.RWMutex
    logger   *zap.Logger
    metrics  *prometheus.CounterVec
}

func (m *StatefulMiddleware) Provision(ctx caddy.Context) error {
    m.logger = ctx.Logger(m)
    
    // 初始化Prometheus指标
    m.metrics = prometheus.NewCounterVec(
        prometheus.CounterOpts{
            Name: "caddy_custom_requests_total",
            Help: "Total number of requests processed by custom middleware",
        },
        []string{"method", "status"},
    )
    
    // 注册指标
    prometheus.MustRegister(m.metrics)
    
    return nil
}

func (m *StatefulMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
    // 增加计数器
    m.mutex.Lock()
    m.counter++
    currentCount := m.counter
    m.mutex.Unlock()
    
    // 添加请求ID
    requestID := fmt.Sprintf("%d-%d", time.Now().Unix(), currentCount)
    r.Header.Set("X-Request-ID", requestID)
    w.Header().Set("X-Request-ID", requestID)
    
    // 创建响应记录器
    recorder := caddyhttp.NewResponseRecorder(w, nil, nil)
    
    // 处理请求
    err := next.ServeHTTP(recorder, r)
    
    // 记录指标
    m.metrics.WithLabelValues(
        r.Method,
        fmt.Sprintf("%d", recorder.Status()),
    ).Inc()
    
    return err
}

// Cleanup 清理资源
func (m *StatefulMiddleware) Cleanup() error {
    if m.metrics != nil {
        prometheus.Unregister(m.metrics)
    }
    return nil
}

9.2.3 请求/响应修改中间件

// 请求/响应修改中间件
type RequestResponseModifier struct {
    RequestHeaders  map[string]string `json:"request_headers,omitempty"`
    ResponseHeaders map[string]string `json:"response_headers,omitempty"`
    RemoveHeaders   []string         `json:"remove_headers,omitempty"`
    BodyTransform   string           `json:"body_transform,omitempty"`
}

func (m RequestResponseModifier) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
    // 修改请求头
    for key, value := range m.RequestHeaders {
        r.Header.Set(key, value)
    }
    
    // 删除指定头部
    for _, header := range m.RemoveHeaders {
        r.Header.Del(header)
    }
    
    // 创建响应包装器
    wrapper := &responseWrapper{
        ResponseWriter: w,
        modifier:      &m,
    }
    
    return next.ServeHTTP(wrapper, r)
}

type responseWrapper struct {
    http.ResponseWriter
    modifier *RequestResponseModifier
    written  bool
}

func (rw *responseWrapper) WriteHeader(statusCode int) {
    if !rw.written {
        // 添加响应头
        for key, value := range rw.modifier.ResponseHeaders {
            rw.Header().Set(key, value)
        }
        rw.written = true
    }
    rw.ResponseWriter.WriteHeader(statusCode)
}

func (rw *responseWrapper) Write(data []byte) (int, error) {
    if !rw.written {
        rw.WriteHeader(http.StatusOK)
    }
    
    // 可以在这里对响应体进行转换
    if rw.modifier.BodyTransform != "" {
        // 实现响应体转换逻辑
        data = rw.transformBody(data)
    }
    
    return rw.ResponseWriter.Write(data)
}

func (rw *responseWrapper) transformBody(data []byte) []byte {
    // 实现具体的转换逻辑
    switch rw.modifier.BodyTransform {
    case "uppercase":
        return []byte(strings.ToUpper(string(data)))
    case "base64":
        return []byte(base64.StdEncoding.EncodeToString(data))
    default:
        return data
    }
}

9.3 高级匹配器开发

9.3.1 自定义匹配器

package custommatcher

import (
    "net/http"
    "regexp"
    "strings"
    
    "github.com/caddyserver/caddy/v2"
    "github.com/caddyserver/caddy/v2/modules/caddyhttp"
)

func init() {
    caddy.RegisterModule(CustomMatcher{})
}

// CustomMatcher 自定义匹配器
type CustomMatcher struct {
    UserAgent   string `json:"user_agent,omitempty"`
    IPRange     string `json:"ip_range,omitempty"`
    TimeRange   string `json:"time_range,omitempty"`
    HeaderMatch map[string]string `json:"header_match,omitempty"`
    
    userAgentRegex *regexp.Regexp
    ipNet          *net.IPNet
}

func (CustomMatcher) CaddyModule() caddy.ModuleInfo {
    return caddy.ModuleInfo{
        ID:  "http.matchers.custom",
        New: func() caddy.Module { return new(CustomMatcher) },
    }
}

func (m *CustomMatcher) Provision(ctx caddy.Context) error {
    // 编译用户代理正则表达式
    if m.UserAgent != "" {
        regex, err := regexp.Compile(m.UserAgent)
        if err != nil {
            return fmt.Errorf("invalid user agent regex: %v", err)
        }
        m.userAgentRegex = regex
    }
    
    // 解析IP范围
    if m.IPRange != "" {
        _, ipNet, err := net.ParseCIDR(m.IPRange)
        if err != nil {
            return fmt.Errorf("invalid IP range: %v", err)
        }
        m.ipNet = ipNet
    }
    
    return nil
}

func (m CustomMatcher) Match(r *http.Request) bool {
    // 匹配用户代理
    if m.userAgentRegex != nil {
        userAgent := r.Header.Get("User-Agent")
        if !m.userAgentRegex.MatchString(userAgent) {
            return false
        }
    }
    
    // 匹配IP范围
    if m.ipNet != nil {
        clientIP := net.ParseIP(r.RemoteAddr)
        if clientIP == nil || !m.ipNet.Contains(clientIP) {
            return false
        }
    }
    
    // 匹配时间范围
    if m.TimeRange != "" {
        if !m.matchTimeRange() {
            return false
        }
    }
    
    // 匹配自定义头部
    for header, expectedValue := range m.HeaderMatch {
        actualValue := r.Header.Get(header)
        if actualValue != expectedValue {
            return false
        }
    }
    
    return true
}

func (m CustomMatcher) matchTimeRange() bool {
    // 实现时间范围匹配逻辑
    // 例如:"09:00-17:00" 表示工作时间
    now := time.Now()
    hour := now.Hour()
    
    // 简单示例:工作时间匹配
    if m.TimeRange == "business_hours" {
        return hour >= 9 && hour < 17
    }
    
    return true
}

// Interface guard
var _ caddyhttp.RequestMatcher = (*CustomMatcher)(nil)

9.3.2 复合匹配器

// 复合匹配器
type CompoundMatcher struct {
    And []caddyhttp.RequestMatcher `json:"and,omitempty"`
    Or  []caddyhttp.RequestMatcher `json:"or,omitempty"`
    Not caddyhttp.RequestMatcher   `json:"not,omitempty"`
}

func (m CompoundMatcher) Match(r *http.Request) bool {
    // AND逻辑:所有条件都必须满足
    if len(m.And) > 0 {
        for _, matcher := range m.And {
            if !matcher.Match(r) {
                return false
            }
        }
    }
    
    // OR逻辑:至少一个条件满足
    if len(m.Or) > 0 {
        matched := false
        for _, matcher := range m.Or {
            if matcher.Match(r) {
                matched = true
                break
            }
        }
        if !matched {
            return false
        }
    }
    
    // NOT逻辑:条件不能满足
    if m.Not != nil {
        if m.Not.Match(r) {
            return false
        }
    }
    
    return true
}

9.4 存储提供商开发

9.4.1 自定义存储后端

package customstorage

import (
    "context"
    "fmt"
    "io"
    "io/fs"
    "time"
    
    "github.com/caddyserver/caddy/v2"
    "github.com/caddyserver/certmagic"
)

func init() {
    caddy.RegisterModule(CustomStorage{})
}

// CustomStorage 自定义存储提供商
type CustomStorage struct {
    Endpoint   string `json:"endpoint,omitempty"`
    AccessKey  string `json:"access_key,omitempty"`
    SecretKey  string `json:"secret_key,omitempty"`
    BucketName string `json:"bucket_name,omitempty"`
    
    client interface{} // 存储客户端
}

func (CustomStorage) CaddyModule() caddy.ModuleInfo {
    return caddy.ModuleInfo{
        ID:  "caddy.storage.custom",
        New: func() caddy.Module { return new(CustomStorage) },
    }
}

func (s *CustomStorage) Provision(ctx caddy.Context) error {
    // 初始化存储客户端
    // s.client = createStorageClient(s.Endpoint, s.AccessKey, s.SecretKey)
    return nil
}

func (s *CustomStorage) CertMagicStorage() (certmagic.Storage, error) {
    return s, nil
}

// 实现certmagic.Storage接口
func (s *CustomStorage) Store(key string, value []byte) error {
    // 实现存储逻辑
    fmt.Printf("Storing key: %s, size: %d bytes\n", key, len(value))
    return nil
}

func (s *CustomStorage) Load(key string) ([]byte, error) {
    // 实现加载逻辑
    fmt.Printf("Loading key: %s\n", key)
    return nil, fmt.Errorf("key not found: %s", key)
}

func (s *CustomStorage) Delete(key string) error {
    // 实现删除逻辑
    fmt.Printf("Deleting key: %s\n", key)
    return nil
}

func (s *CustomStorage) Exists(key string) bool {
    // 实现存在性检查
    fmt.Printf("Checking existence of key: %s\n", key)
    return false
}

func (s *CustomStorage) List(prefix string, recursive bool) ([]string, error) {
    // 实现列表功能
    fmt.Printf("Listing keys with prefix: %s, recursive: %v\n", prefix, recursive)
    return []string{}, nil
}

func (s *CustomStorage) Stat(key string) (certmagic.KeyInfo, error) {
    // 实现状态查询
    return certmagic.KeyInfo{
        Key:        key,
        Modified:   time.Now(),
        Size:       0,
        IsTerminal: true,
    }, nil
}

// Interface guards
var (
    _ caddy.Provisioner    = (*CustomStorage)(nil)
    _ caddy.StorageConverter = (*CustomStorage)(nil)
    _ certmagic.Storage    = (*CustomStorage)(nil)
)

9.4.2 分布式存储实现

// 分布式存储实现
type DistributedStorage struct {
    Nodes     []string `json:"nodes,omitempty"`
    Replicas  int      `json:"replicas,omitempty"`
    Timeout   caddy.Duration `json:"timeout,omitempty"`
    
    clients   []StorageClient
    hashRing  *consistent.Consistent
}

type StorageClient interface {
    Store(key string, value []byte) error
    Load(key string) ([]byte, error)
    Delete(key string) error
    Exists(key string) bool
}

func (ds *DistributedStorage) Provision(ctx caddy.Context) error {
    // 初始化一致性哈希环
    ds.hashRing = consistent.New()
    
    // 添加节点到哈希环
    for _, node := range ds.Nodes {
        ds.hashRing.Add(node)
        
        // 创建客户端连接
        client := createStorageClient(node)
        ds.clients = append(ds.clients, client)
    }
    
    return nil
}

func (ds *DistributedStorage) Store(key string, value []byte) error {
    // 获取负责该key的节点
    nodes, err := ds.hashRing.GetN(key, ds.Replicas)
    if err != nil {
        return err
    }
    
    // 并行存储到多个副本
    errChan := make(chan error, len(nodes))
    
    for _, node := range nodes {
        go func(n string) {
            client := ds.getClientForNode(n)
            errChan <- client.Store(key, value)
        }(node)
    }
    
    // 等待所有存储操作完成
    var errors []error
    for i := 0; i < len(nodes); i++ {
        if err := <-errChan; err != nil {
            errors = append(errors, err)
        }
    }
    
    // 如果大多数副本存储成功,则认为操作成功
    if len(errors) <= len(nodes)/2 {
        return nil
    }
    
    return fmt.Errorf("failed to store to majority of replicas: %v", errors)
}

func (ds *DistributedStorage) Load(key string) ([]byte, error) {
    // 从任意一个副本读取
    nodes, err := ds.hashRing.GetN(key, ds.Replicas)
    if err != nil {
        return nil, err
    }
    
    for _, node := range nodes {
        client := ds.getClientForNode(node)
        if data, err := client.Load(key); err == nil {
            return data, nil
        }
    }
    
    return nil, fmt.Errorf("key not found in any replica: %s", key)
}

func (ds *DistributedStorage) getClientForNode(node string) StorageClient {
    // 根据节点名称获取对应的客户端
    for i, n := range ds.Nodes {
        if n == node {
            return ds.clients[i]
        }
    }
    return nil
}

9.5 DNS提供商开发

9.5.1 自定义DNS提供商

package customdns

import (
    "context"
    "fmt"
    "time"
    
    "github.com/caddyserver/caddy/v2"
    "github.com/libdns/libdns"
)

func init() {
    caddy.RegisterModule(Provider{})
}

// Provider 自定义DNS提供商
type Provider struct {
    APIKey    string `json:"api_key,omitempty"`
    APISecret string `json:"api_secret,omitempty"
    Endpoint  string `json:"endpoint,omitempty"`
    
    client DNSClient
}

type DNSClient interface {
    CreateRecord(zone, name, recordType, value string, ttl int) error
    DeleteRecord(zone, name, recordType string) error
    GetRecords(zone string) ([]libdns.Record, error)
}

func (Provider) CaddyModule() caddy.ModuleInfo {
    return caddy.ModuleInfo{
        ID:  "dns.providers.custom",
        New: func() caddy.Module { return new(Provider) },
    }
}

func (p *Provider) Provision(ctx caddy.Context) error {
    // 初始化DNS客户端
    p.client = NewDNSClient(p.APIKey, p.APISecret, p.Endpoint)
    return nil
}

// 实现libdns.RecordGetter接口
func (p *Provider) GetRecords(ctx context.Context, zone string) ([]libdns.Record, error) {
    records, err := p.client.GetRecords(zone)
    if err != nil {
        return nil, fmt.Errorf("failed to get records: %v", err)
    }
    return records, nil
}

// 实现libdns.RecordAppender接口
func (p *Provider) AppendRecords(ctx context.Context, zone string, records []libdns.Record) ([]libdns.Record, error) {
    var createdRecords []libdns.Record
    
    for _, record := range records {
        err := p.client.CreateRecord(
            zone,
            record.Name,
            record.Type,
            record.Value,
            int(record.TTL.Seconds()),
        )
        if err != nil {
            return nil, fmt.Errorf("failed to create record %s: %v", record.Name, err)
        }
        
        // 设置记录ID(如果API返回)
        record.ID = fmt.Sprintf("%s-%s-%s", zone, record.Name, record.Type)
        createdRecords = append(createdRecords, record)
    }
    
    return createdRecords, nil
}

// 实现libdns.RecordDeleter接口
func (p *Provider) DeleteRecords(ctx context.Context, zone string, records []libdns.Record) ([]libdns.Record, error) {
    var deletedRecords []libdns.Record
    
    for _, record := range records {
        err := p.client.DeleteRecord(zone, record.Name, record.Type)
        if err != nil {
            return nil, fmt.Errorf("failed to delete record %s: %v", record.Name, err)
        }
        deletedRecords = append(deletedRecords, record)
    }
    
    return deletedRecords, nil
}

// Interface guards
var (
    _ caddy.Provisioner      = (*Provider)(nil)
    _ libdns.RecordGetter    = (*Provider)(nil)
    _ libdns.RecordAppender  = (*Provider)(nil)
    _ libdns.RecordDeleter   = (*Provider)(nil)
)

9.5.2 DNS客户端实现

// DNS客户端实现
type dnsClient struct {
    apiKey    string
    apiSecret string
    endpoint  string
    httpClient *http.Client
}

func NewDNSClient(apiKey, apiSecret, endpoint string) DNSClient {
    return &dnsClient{
        apiKey:    apiKey,
        apiSecret: apiSecret,
        endpoint:  endpoint,
        httpClient: &http.Client{
            Timeout: 30 * time.Second,
        },
    }
}

func (c *dnsClient) CreateRecord(zone, name, recordType, value string, ttl int) error {
    payload := map[string]interface{}{
        "name":  name,
        "type":  recordType,
        "value": value,
        "ttl":   ttl,
    }
    
    return c.makeRequest("POST", fmt.Sprintf("/zones/%s/records", zone), payload)
}

func (c *dnsClient) DeleteRecord(zone, name, recordType string) error {
    return c.makeRequest("DELETE", fmt.Sprintf("/zones/%s/records/%s/%s", zone, name, recordType), nil)
}

func (c *dnsClient) GetRecords(zone string) ([]libdns.Record, error) {
    var response struct {
        Records []struct {
            ID    string `json:"id"`
            Name  string `json:"name"`
            Type  string `json:"type"`
            Value string `json:"value"`
            TTL   int    `json:"ttl"`
        } `json:"records"`
    }
    
    err := c.makeRequest("GET", fmt.Sprintf("/zones/%s/records", zone), &response)
    if err != nil {
        return nil, err
    }
    
    var records []libdns.Record
    for _, r := range response.Records {
        records = append(records, libdns.Record{
            ID:    r.ID,
            Name:  r.Name,
            Type:  r.Type,
            Value: r.Value,
            TTL:   time.Duration(r.TTL) * time.Second,
        })
    }
    
    return records, nil
}

func (c *dnsClient) makeRequest(method, path string, payload interface{}) error {
    url := c.endpoint + path
    
    var body io.Reader
    if payload != nil {
        jsonData, err := json.Marshal(payload)
        if err != nil {
            return err
        }
        body = bytes.NewBuffer(jsonData)
    }
    
    req, err := http.NewRequest(method, url, body)
    if err != nil {
        return err
    }
    
    // 添加认证头
    req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.apiKey))
    req.Header.Set("Content-Type", "application/json")
    
    resp, err := c.httpClient.Do(req)
    if err != nil {
        return err
    }
    defer resp.Body.Close()
    
    if resp.StatusCode >= 400 {
        return fmt.Errorf("API request failed with status %d", resp.StatusCode)
    }
    
    return nil
}

9.6 企业级功能

9.6.1 集群配置同步

// 集群配置同步
type ClusterSync struct {
    Nodes       []string `json:"nodes,omitempty"`
    SyncInterval caddy.Duration `json:"sync_interval,omitempty"`
    
    ticker   *time.Ticker
    stopChan chan struct{}
}

func (cs *ClusterSync) Provision(ctx caddy.Context) error {
    if cs.SyncInterval == 0 {
        cs.SyncInterval = caddy.Duration(30 * time.Second)
    }
    
    cs.stopChan = make(chan struct{})
    cs.ticker = time.NewTicker(time.Duration(cs.SyncInterval))
    
    // 启动同步协程
    go cs.syncLoop()
    
    return nil
}

func (cs *ClusterSync) syncLoop() {
    for {
        select {
        case <-cs.ticker.C:
            cs.syncConfiguration()
        case <-cs.stopChan:
            return
        }
    }
}

func (cs *ClusterSync) syncConfiguration() {
    // 获取本地配置
    localConfig := cs.getLocalConfig()
    
    // 与其他节点同步
    for _, node := range cs.Nodes {
        go func(nodeAddr string) {
            remoteConfig, err := cs.getRemoteConfig(nodeAddr)
            if err != nil {
                return
            }
            
            // 比较配置版本
            if remoteConfig.Version > localConfig.Version {
                cs.updateLocalConfig(remoteConfig)
            }
        }(node)
    }
}

func (cs *ClusterSync) getLocalConfig() *ClusterConfig {
    // 实现获取本地配置逻辑
    return &ClusterConfig{}
}

func (cs *ClusterSync) getRemoteConfig(nodeAddr string) (*ClusterConfig, error) {
    // 实现获取远程配置逻辑
    resp, err := http.Get(fmt.Sprintf("http://%s/api/config", nodeAddr))
    if err != nil {
        return nil, err
    }
    defer resp.Body.Close()
    
    var config ClusterConfig
    err = json.NewDecoder(resp.Body).Decode(&config)
    return &config, err
}

type ClusterConfig struct {
    Version int64       `json:"version"`
    Config  interface{} `json:"config"`
}

9.6.2 高可用性配置

// 高可用性配置
type HAConfig struct {
    VirtualIP     string   `json:"virtual_ip,omitempty"`
    Priority      int      `json:"priority,omitempty"`
    CheckInterval caddy.Duration `json:"check_interval,omitempty"`
    Peers         []string `json:"peers,omitempty"`
    
    isMaster   bool
    healthChan chan bool
}

func (ha *HAConfig) Provision(ctx caddy.Context) error {
    ha.healthChan = make(chan bool, 1)
    
    // 启动健康检查
    go ha.healthCheck()
    
    // 启动选主逻辑
    go ha.leaderElection()
    
    return nil
}

func (ha *HAConfig) healthCheck() {
    ticker := time.NewTicker(time.Duration(ha.CheckInterval))
    defer ticker.Stop()
    
    for range ticker.C {
        healthy := ha.checkHealth()
        select {
        case ha.healthChan <- healthy:
        default:
        }
    }
}

func (ha *HAConfig) checkHealth() bool {
    // 实现健康检查逻辑
    // 检查关键服务状态
    return true
}

func (ha *HAConfig) leaderElection() {
    for health := range ha.healthChan {
        if health && !ha.isMaster {
            // 尝试成为主节点
            if ha.tryBecomeMaster() {
                ha.isMaster = true
                ha.activateVirtualIP()
            }
        } else if !health && ha.isMaster {
            // 释放主节点角色
            ha.isMaster = false
            ha.deactivateVirtualIP()
        }
    }
}

func (ha *HAConfig) tryBecomeMaster() bool {
    // 实现选主逻辑(例如使用etcd或consul)
    return true
}

func (ha *HAConfig) activateVirtualIP() {
    // 激活虚拟IP
    cmd := exec.Command("ip", "addr", "add", ha.VirtualIP, "dev", "eth0")
    cmd.Run()
}

func (ha *HAConfig) deactivateVirtualIP() {
    // 停用虚拟IP
    cmd := exec.Command("ip", "addr", "del", ha.VirtualIP, "dev", "eth0")
    cmd.Run()
}

9.7 性能优化技巧

9.7.1 连接池管理

// 连接池管理
type ConnectionPool struct {
    MaxConnections int `json:"max_connections,omitempty"`
    IdleTimeout    caddy.Duration `json:"idle_timeout,omitempty"`
    
    pool   sync.Pool
    active int64
    mutex  sync.RWMutex
}

func (cp *ConnectionPool) Provision(ctx caddy.Context) error {
    cp.pool = sync.Pool{
        New: func() interface{} {
            return cp.createConnection()
        },
    }
    return nil
}

func (cp *ConnectionPool) GetConnection() (net.Conn, error) {
    cp.mutex.Lock()
    defer cp.mutex.Unlock()
    
    if atomic.LoadInt64(&cp.active) >= int64(cp.MaxConnections) {
        return nil, fmt.Errorf("connection pool exhausted")
    }
    
    conn := cp.pool.Get().(net.Conn)
    atomic.AddInt64(&cp.active, 1)
    
    return conn, nil
}

func (cp *ConnectionPool) ReleaseConnection(conn net.Conn) {
    atomic.AddInt64(&cp.active, -1)
    cp.pool.Put(conn)
}

func (cp *ConnectionPool) createConnection() net.Conn {
    // 创建新连接的逻辑
    return nil
}

9.7.2 缓存优化

// 智能缓存中间件
type SmartCache struct {
    TTL        caddy.Duration `json:"ttl,omitempty"`
    MaxSize    int           `json:"max_size,omitempty"`
    CacheRules []CacheRule   `json:"cache_rules,omitempty"`
    
    cache *lru.Cache
    stats CacheStats
}

type CacheRule struct {
    Path        string         `json:"path,omitempty"`
    Methods     []string       `json:"methods,omitempty"`
    TTL         caddy.Duration `json:"ttl,omitempty"`
    VaryHeaders []string       `json:"vary_headers,omitempty"`
}

type CacheStats struct {
    Hits   int64 `json:"hits"`
    Misses int64 `json:"misses"`
    Size   int64 `json:"size"`
}

func (sc *SmartCache) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyhttp.Handler) error {
    // 检查是否应该缓存
    rule := sc.matchCacheRule(r)
    if rule == nil {
        return next.ServeHTTP(w, r)
    }
    
    // 生成缓存键
    cacheKey := sc.generateCacheKey(r, rule)
    
    // 尝试从缓存获取
    if cached, ok := sc.cache.Get(cacheKey); ok {
        atomic.AddInt64(&sc.stats.Hits, 1)
        cachedResponse := cached.(*CachedResponse)
        
        // 检查是否过期
        if time.Since(cachedResponse.Timestamp) < time.Duration(rule.TTL) {
            sc.writeCachedResponse(w, cachedResponse)
            return nil
        }
    }
    
    atomic.AddInt64(&sc.stats.Misses, 1)
    
    // 创建响应记录器
    recorder := &cacheRecorder{
        ResponseWriter: w,
        statusCode:     200,
        headers:        make(http.Header),
    }
    
    // 处理请求
    err := next.ServeHTTP(recorder, r)
    if err != nil {
        return err
    }
    
    // 缓存响应
    if sc.shouldCache(recorder.statusCode) {
        cachedResponse := &CachedResponse{
            StatusCode: recorder.statusCode,
            Headers:    recorder.headers,
            Body:       recorder.body.Bytes(),
            Timestamp:  time.Now(),
        }
        sc.cache.Add(cacheKey, cachedResponse)
    }
    
    return nil
}

type CachedResponse struct {
    StatusCode int
    Headers    http.Header
    Body       []byte
    Timestamp  time.Time
}

type cacheRecorder struct {
    http.ResponseWriter
    statusCode int
    headers    http.Header
    body       bytes.Buffer
}

func (cr *cacheRecorder) WriteHeader(statusCode int) {
    cr.statusCode = statusCode
    cr.ResponseWriter.WriteHeader(statusCode)
}

func (cr *cacheRecorder) Write(data []byte) (int, error) {
    cr.body.Write(data)
    return cr.ResponseWriter.Write(data)
}

9.8 本章总结

本章深入探讨了Caddy的高级特性和扩展开发:

  1. 架构理解:模块化设计和请求处理流程
  2. 中间件开发:自定义处理逻辑和状态管理
  3. 匹配器开发:复杂的请求匹配逻辑
  4. 存储提供商:自定义存储后端和分布式存储
  5. DNS提供商:自动化证书管理的DNS集成
  6. 企业功能:集群同步和高可用性配置
  7. 性能优化:连接池和智能缓存

9.9 练习题

  1. 开发一个请求限流中间件,支持多种限流策略
  2. 实现一个基于Redis的分布式存储提供商
  3. 创建一个自定义DNS提供商,集成您的DNS服务
  4. 开发一个API网关中间件,支持认证和路由
  5. 实现一个监控中间件,收集详细的性能指标

下一章预告:第十章将通过一个完整的实战项目,展示如何使用Caddy构建企业级的Web服务架构。