package initialize import ( "context" "crypto/tls" "encoding/json" "errors" "fmt" "github.com/TremblingV5/DouTok/pkg/constants" "github.com/TremblingV5/DouTok/pkg/dtnetwork" "time" "github.com/TremblingV5/DouTok/applications/api/initialize/rpc" "github.com/cloudwego/hertz/pkg/app/server" "github.com/cloudwego/hertz/pkg/app/server/registry" "github.com/cloudwego/hertz/pkg/common/config" "github.com/cloudwego/hertz/pkg/common/hlog" "github.com/cloudwego/hertz/pkg/common/utils" "github.com/hertz-contrib/gzip" h2config "github.com/hertz-contrib/http2/config" "github.com/hertz-contrib/http2/factory" "github.com/hertz-contrib/obs-opentelemetry/provider" hertztracing "github.com/hertz-contrib/obs-opentelemetry/tracing" "github.com/hertz-contrib/registry/etcd" ) var ( ServiceAddr string EtcdAddress string hertzCfg HertzCfg ) type HertzCfg struct { UseNetpoll bool `json:"UseNetpoll" yaml:"UseNetpoll"` Http2 Http2 `json:"Http2" yaml:"Http2"` Tls Tls `json:"Tls" yaml:"Tls"` } type Tls struct { Enable bool `json:"Enable" yaml:"Enable"` Cfg tls.Config Cert string `json:"CertFile" yaml:"CertFile"` Key string `json:"KeyFile" yaml:"KeyFile"` ALPN bool `json:"ALPN" yaml:"ALPN"` } type Http2 struct { Enable bool `json:"Enable" yaml:"Enable"` DisableKeepalive bool `json:"DisableKeepalive" yaml:"DisableKeepalive"` ReadTimeout Duration `json:"ReadTimeout" yaml:"ReadTimeout"` } type Duration struct { time.Duration } func (d Duration) MarshalJSON() ([]byte, error) { return json.Marshal(d.String()) } func (d *Duration) UnmarshalJSON(b []byte) error { var v interface{} if err := json.Unmarshal(b, &v); err != nil { return err } switch value := v.(type) { case float64: d.Duration = time.Duration(value) return nil case string: var err error d.Duration, err = time.ParseDuration(value) if err != nil { return err } return nil default: return errors.New("invalid duration") } } // 初始化 API 配置 func Init() { InitViper() rpc.InitRPC() InitJwt() InitRedisClient() } func InitHertzCfg() { ServiceAddr = fmt.Sprintf("%s:%d", ViperConfig.Viper.GetString("Server.Address"), ViperConfig.Viper.GetInt("Server.Port")) EtcdAddress = fmt.Sprintf("%s:%d", ViperConfig.Viper.GetString("Etcd.Address"), ViperConfig.Viper.GetInt("Etcd.Port")) hertzV, err := json.Marshal(ViperConfig.Viper.Sub("Hertz").AllSettings()) if err != nil { hlog.Fatalf("Error marshalling Hertz config %s", err) } if err := json.Unmarshal(hertzV, &hertzCfg); err != nil { hlog.Fatalf("Error unmarshalling Hertz config %s", err) } } // 初始化 Hertz func InitHertz() (*server.Hertz, func()) { InitHertzCfg() opts := []config.Option{server.WithHostPorts(ServiceAddr)} opts = append(opts, server.WithMaxRequestBodySize(1024*1024*1024)) // 服务注册 if ViperConfig.Viper.GetBool("Etcd.Enable") { r, err := etcd.NewEtcdRegistry([]string{EtcdAddress}) if err != nil { hlog.Fatal(err) } opts = append(opts, server.WithRegistry(r, ®istry.Info{ ServiceName: constants.ApiServerName, Addr: utils.NewNetAddr("tcp", ServiceAddr), Weight: 10, Tags: nil, })) } var p provider.OtelProvider if ViperConfig.Viper.GetBool("Otel.Enable") { //链路追踪 p = provider.NewOpenTelemetryProvider( provider.WithServiceName(constants.ApiServerName), provider.WithExportEndpoint(fmt.Sprintf("%s:%s", ViperConfig.Viper.GetString("Otel.Host"), ViperConfig.Viper.GetString("Otel.Port"))), provider.WithInsecure(), ) } tracer, tracerCfg := hertztracing.NewServerTracer() opts = append(opts, tracer) // 网络库 hertzNet := dtnetwork.GetTransporter(hertzCfg.UseNetpoll) opts = append(opts, server.WithTransport(hertzNet)) // TLS & Http2 tlsEnable := hertzCfg.Tls.Enable h2Enable := hertzCfg.Http2.Enable hertzCfg.Tls.Cfg = tls.Config{ MinVersion: tls.VersionTLS12, CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256}, CipherSuites: []uint16{ tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305, tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, }, } if tlsEnable { cert, err := tls.LoadX509KeyPair(hertzCfg.Tls.Cert, hertzCfg.Tls.Key) if err != nil { hlog.Error(err) } hertzCfg.Tls.Cfg.Certificates = append(hertzCfg.Tls.Cfg.Certificates, cert) opts = append(opts, server.WithTLS(&hertzCfg.Tls.Cfg)) if alpn := hertzCfg.Tls.ALPN; alpn { opts = append(opts, server.WithALPN(alpn)) } } else if h2Enable { opts = append(opts, server.WithH2C(h2Enable)) } // Hertz h := server.Default(opts...) h.Use(gzip.Gzip(gzip.DefaultCompression), hertztracing.ServerMiddleware(tracerCfg)) // Protocol if h2Enable { h.AddProtocol("h2", factory.NewServerFactory( h2config.WithReadTimeout(hertzCfg.Http2.ReadTimeout.Duration), h2config.WithDisableKeepAlive(hertzCfg.Http2.DisableKeepalive))) if tlsEnable { hertzCfg.Tls.Cfg.NextProtos = append(hertzCfg.Tls.Cfg.NextProtos, "h2") } } if ViperConfig.Viper.GetBool("Otel.Enable") { return h, func() { } } return h, func() { _ = p.Shutdown(context.Background()) //nolint } }