数据打点、Http优化

tags/v0.0.3
zhuxianglong 2 months ago
parent 47a82f1878
commit a37ea90246

@ -2,6 +2,12 @@ module gitea.weitiangame.com/sdk/wt-game
go 1.20 go 1.20
require github.com/go-resty/resty/v2 v2.16.3 require (
github.com/go-resty/resty/v2 v2.16.3
go.uber.org/zap v1.27.0
)
require golang.org/x/net v0.33.0 // indirect require (
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/net v0.33.0 // indirect
)

@ -1,5 +1,14 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/go-resty/resty/v2 v2.16.3 h1:zacNT7lt4b8M/io2Ahj6yPypL7bqx9n1iprfQuodV+E= github.com/go-resty/resty/v2 v2.16.3 h1:zacNT7lt4b8M/io2Ahj6yPypL7bqx9n1iprfQuodV+E=
github.com/go-resty/resty/v2 v2.16.3/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA= github.com/go-resty/resty/v2 v2.16.3/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U= golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

@ -0,0 +1,46 @@
package point
import (
"gitea.weitiangame.com/sdk/wt-game/utils/ahttp"
"github.com/go-resty/resty/v2"
"go.uber.org/zap"
"sync"
)
var (
instance *Point
once sync.Once
)
type Point struct {
clientID string
logger *zap.Logger
ahttp *resty.Request
}
// New returns the singleton instance of Point.
func New(clientID string, logger *zap.Logger) *Point {
once.Do(func() {
instance = &Point{
clientID: clientID,
logger: logger,
}
if instance.logger == nil {
var err error
instance.logger, err = zap.NewProduction()
if err != nil {
panic(err)
}
}
instance.ahttp = ahttp.New(nil).SetLog(instance.logger).Client()
})
return instance
}
// Event sends an event to the specified URL.
func (p *Point) Event(data map[string]interface{}) (*resty.Response, error) {
return p.ahttp.SetBody(data).Post("https://e.tapdb.net/v2/event")
}

@ -0,0 +1,19 @@
package test
import (
"fmt"
"gitea.weitiangame.com/sdk/wt-game/point"
"testing"
)
var pointSdk = point.New("your-client-id", nil)
// TestOrderSign 测试订单签名
func TestPoint(t *testing.T) {
event, err := pointSdk.Event(map[string]interface{}{
"test": "test",
})
fmt.Println(event)
fmt.Println(err)
}

@ -0,0 +1,167 @@
package ahttp
import (
"crypto/tls"
"github.com/go-resty/resty/v2"
"go.uber.org/zap"
"net"
"net/http"
"runtime"
"sync"
"time"
)
// Config 包含 HTTP 客户端的配置选项
// Config contains the configuration options for the HTTP client
type Config struct {
MaxIdleConnections int // 连接池的最大空闲连接数 / Maximum idle connections in the connection pool
IdleConnectionTimeout time.Duration // 空闲连接超时时间 / Timeout for idle connections
DisableCompression bool // 禁用压缩 / Disable compression
DisableKeepAlives bool // 禁用 keep-alive / Disable keep-alive
InsecureSkipVerify bool // 跳过 TLS 证书验证 / Skip TLS certificate verification
Timeout time.Duration // 总超时时间 / Total timeout duration
TLSHandshakeTimeout time.Duration // TLS 握手超时时间 / Timeout for TLS handshake
ExpectContinueTimeout time.Duration // 100-continue 超时时间 / Timeout for 100-continue
MaxConnectionsPerHost int // 每主机的最大连接数 / Maximum connections per host
RetryAttempts int // 请求重试次数 / Number of retry attempts for failed requests
DialerTimeout time.Duration // Dialer 的连接超时时间 / Dialer connection timeout
DialerKeepAlive time.Duration // Dialer 的 Keep-Alive 时间 / Dialer keep-alive time
}
// HttpClient 是对 Resty 客户端的封装,支持自定义配置和日志 / HttpClient is a wrapper for the Resty client with custom configuration and logging support
type HttpClient struct {
httpClient *resty.Client // Resty 客户端实例 / Resty client instance
httpTransport *http.Transport // HTTP 传输层配置 / HTTP transport layer configuration
logger *zap.Logger // 日志记录器 / Logger instance
config *Config
}
var (
singletonClient *HttpClient
once sync.Once
)
// New 创建一个新的 HTTP 客户端实例 / NewHttpClient creates a new HTTP client instance
func New(config *Config) *HttpClient {
once.Do(func() {
if config == nil {
config = defaultConfig()
}
singletonClient = &HttpClient{
httpClient: newRestyClient(config),
httpTransport: newTransport(config),
config: config,
}
})
return singletonClient
}
// newRestyClient 配置 Resty 客户端 / Configures the Resty client
func newRestyClient(config *Config) *resty.Client {
client := resty.NewWithClient(&http.Client{
Transport: newTransport(config),
Timeout: config.Timeout,
})
client.SetRetryCount(config.RetryAttempts)
client.SetRetryWaitTime(1 * time.Second)
client.SetRetryMaxWaitTime(10 * time.Second)
return client
}
// defaultConfig 返回默认的配置值 / Returns the default configuration values
func defaultConfig() *Config {
return &Config{
MaxIdleConnections: runtime.GOMAXPROCS(0) * 200,
IdleConnectionTimeout: 120 * time.Second,
DisableCompression: false,
Timeout: 90 * time.Second,
TLSHandshakeTimeout: 30 * time.Second,
ExpectContinueTimeout: 2 * time.Second,
MaxConnectionsPerHost: runtime.GOMAXPROCS(0) * 100,
RetryAttempts: 3,
DialerTimeout: 15 * time.Second, // 默认 Dialer 超时时间
DialerKeepAlive: 60 * time.Second, // 默认 Dialer Keep-Alive 时间
}
}
// newTransport 创建并配置 HTTP 传输层 / Creates and configures the HTTP transport
func newTransport(config *Config) *http.Transport {
tcpDialer := &net.Dialer{
Timeout: config.DialerTimeout,
KeepAlive: config.DialerKeepAlive,
DualStack: true,
}
return &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: tcpDialer.DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: config.MaxIdleConnections,
MaxIdleConnsPerHost: config.MaxConnectionsPerHost,
IdleConnTimeout: config.IdleConnectionTimeout,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: config.InsecureSkipVerify,
MinVersion: tls.VersionTLS12,
CurvePreferences: []tls.CurveID{tls.X25519, tls.CurveP256},
},
TLSHandshakeTimeout: config.TLSHandshakeTimeout,
ExpectContinueTimeout: config.ExpectContinueTimeout,
DisableCompression: config.DisableCompression,
}
}
// SetLog 设置日志记录器 / SetLog sets the logger
func (h *HttpClient) SetLog(logger *zap.Logger) *HttpClient {
h.logger = logger
h.httpClient.OnBeforeRequest(func(c *resty.Client, r *resty.Request) error {
logger.Info("Request",
zap.String("URL", r.URL),
zap.String("Method", r.Method),
zap.Any("Headers", r.Header),
zap.Any("Cookies", r.Cookies),
zap.Any("FormData", r.FormData),
zap.Any("QueryParam", r.QueryParam),
zap.Any("Body", r.Body),
zap.Duration("Timeout", h.config.Timeout))
return nil
})
h.httpClient.OnAfterResponse(func(c *resty.Client, r *resty.Response) error {
if r.StatusCode() >= 400 {
logger.Error("Request failed",
zap.Int("StatusCode", r.StatusCode()),
zap.String("URL", r.Request.URL),
zap.String("Method", r.Request.Method),
zap.Any("Headers", r.Header),
zap.Any("Cookies", r.Cookies),
zap.Any("FormData", r.Request.FormData),
zap.Any("QueryParam", r.Request.QueryParam),
zap.ByteString("Body", r.Body()),
zap.Duration("Duration", time.Since(r.Request.Time)),
)
} else {
logger.Info("Response",
zap.Int("StatusCode", r.StatusCode()),
zap.String("URL", r.Request.URL),
zap.String("Method", r.Request.Method),
zap.Any("Headers", r.Header),
zap.Any("Cookies", r.Cookies),
zap.Any("FormData", r.Request.FormData),
zap.Any("QueryParam", r.Request.QueryParam),
zap.ByteString("Body", r.Body()),
zap.Duration("Duration", time.Since(r.Request.Time)),
)
}
return nil
})
return h
}
// Client 返回 Resty 客户端的请求实例 / Returns a request instance of the Resty client
func (h *HttpClient) Client() *resty.Request {
h.httpClient.SetHeader("User-Agent", "ahttp")
return h.httpClient.R()
}
Loading…
Cancel
Save