package config import ( "context" "net" "os" "sig-pub/pkg/zlog" "time" "github.com/redis/go-redis/v9" clientv3 "go.etcd.io/etcd/client/v3" "golang.org/x/crypto/ssh" "gorm.io/driver/mysql" "gorm.io/driver/postgres" "gorm.io/gorm" "gorm.io/gorm/logger" clickhousev2 "github.com/ClickHouse/clickhouse-go/v2" ) type Configuration struct { // App map[string]any Grpc GrpcConfig Etcd clientv3.Config // Consul api.Config Consul ConsulConfig Database Database Nats NatsConfig Tsdb TsdbConfig } type GrpcConfig struct { Log bool Address string MaxSendMsgSize string MaxRecvMsgSize string ReadBufferSize string WriteBufferSize string keepalive GrpcKeepalive } type GrpcKeepalive struct { IdleTimeout string KeepAliveInterval string KeepAliveTimeout string MaxLifeTime string } type ConsulConfig struct { Address string } // ============== Gate ============== type GateConf struct { HttpAddr string WsAddr string } type NatsConfig struct { Url string } // ============== database ============== type Database struct { Mysql MysqlConfig Postgres PostgresConfig Clickhouse ClickhouseConfig Kvrocks redis.Options } type MysqlConfig struct { LogMode string // silent error warn info gorm.Config Mysql mysql.Config } func (conf MysqlConfig) NewGormDB() (db *gorm.DB, err error) { logLevel := logger.Silent switch conf.LogMode { default: zlog.Errorf("unknow mysql gorm logmode: %s", conf.LogMode) case "": case "silent": logLevel = logger.Silent case "error": logLevel = logger.Error case "warn": logLevel = logger.Warn case "info": logLevel = logger.Info } conf.Logger = logger.Default.LogMode(logLevel) db, err = gorm.Open(mysql.New(conf.Mysql), &conf) return } type PostgresConfig struct { LogMode string // silent error warn info gorm.Config Postgres postgres.Config } func (conf PostgresConfig) NewGormDB() (db *gorm.DB, err error) { logLevel := logger.Silent switch conf.LogMode { default: zlog.Errorf("unknow mysql gorm logmode: %s", conf.LogMode) case "": case "silent": logLevel = logger.Silent case "error": logLevel = logger.Error case "warn": logLevel = logger.Warn case "info": logLevel = logger.Info } conf.Logger = logger.Default.LogMode(logLevel) db, err = gorm.Open(postgres.New(conf.Postgres), &conf) return } type ClickhouseConfig struct { Logsql bool LogsqlCk bool Addr string Database string Username string Password string DialTimeout int // second ReadTimeout int // second DsnParams map[string]any SSH bool SSHUser string SSHAddr string SSHPassword string SSHKey string } func (cfg ClickhouseConfig) Clickhousev2Options() (options *clickhousev2.Options, err error) { options = &clickhousev2.Options{ Addr: []string{cfg.Addr}, DialTimeout: time.Duration(cfg.DialTimeout) * time.Second, ReadTimeout: time.Duration(cfg.ReadTimeout) * time.Second, Auth: clickhousev2.Auth{ Database: cfg.Database, Username: cfg.Username, Password: cfg.Password, }, ClientInfo: clickhousev2.ClientInfo{ Products: []struct { Name string Version string }{ {Name: "sig", Version: "0.1"}, }, }, TLS: nil, // TLS: &tls.Config{ // InsecureSkipVerify: true, // }, // Settings: clickhouse0.Settings{ // "max_execution_time": 60, // "max_query_size": 10000000, // sql最大长度单位byte // }, Settings: clickhousev2.Settings(cfg.DsnParams), Compression: &clickhousev2.Compression{ Method: clickhousev2.CompressionLZ4, }, Debug: cfg.LogsqlCk, Debugf: zlog.Debugf, } if cfg.SSH { var auth []ssh.AuthMethod if cfg.SSHPassword != "" { // SSH 密码认证 auth = append(auth, ssh.Password(cfg.SSHPassword)) } if cfg.SSHKey != "" { // SSH 私钥认证 k, e := os.ReadFile(cfg.SSHKey) if e != nil { return nil, e } signer, e := ssh.ParsePrivateKey(k) if e != nil { return nil, e } auth = append(auth, ssh.PublicKeysCallback(func() ([]ssh.Signer, error) { return []ssh.Signer{signer}, nil })) } sshConfig := &ssh.ClientConfig{ User: cfg.SSHUser, Auth: auth, HostKeyCallback: ssh.InsecureIgnoreHostKey(), // 忽略主机密钥检查(仅供开发使用) Timeout: 5 * time.Second, // SSH 连接超时 } // 连接 SSH 服务器 sshClient, e := ssh.Dial("tcp", cfg.SSHAddr, sshConfig) if e != nil { return nil, e } // 创建本地监听器 (本地端口) localListener, e := sshClient.Dial("tcp", cfg.Addr) // 远程 ClickHouse 地址及端口 if e != nil { return nil, e } // 设置本地 dail 代理 options.DialContext = func(ctx context.Context, addr string) (net.Conn, error) { return localListener, nil } } return } // ============== tsdb ============== type TsdbConfig struct { Active string Victoriametrics VictoriaMetricsConfig } type VictoriaMetricsConfig struct { Addr string } // ============== exchange ============== type OkxExchange struct { ApiKey string SecretKey string Passphrase string ReceiveBuffer int MarketSubscribeLimit int ConsumeBatch int // 订阅 channel 单次处理消息数量 ConsumeLater int // 毫秒,时间到达later或者数据累计到batch触发consume HttpProxy string }