add more options for grpc
This commit is contained in:
parent
86acbf7f66
commit
ee2c05494c
@ -276,9 +276,15 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
type: array
|
type: array
|
||||||
x-go-name: Bypasses
|
x-go-name: Bypasses
|
||||||
|
host:
|
||||||
|
type: string
|
||||||
|
x-go-name: Host
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
x-go-name: Name
|
x-go-name: Name
|
||||||
|
protocol:
|
||||||
|
type: string
|
||||||
|
x-go-name: Protocol
|
||||||
type: object
|
type: object
|
||||||
x-go-package: github.com/go-gost/x/config
|
x-go-package: github.com/go-gost/x/config
|
||||||
ForwarderConfig:
|
ForwarderConfig:
|
||||||
@ -469,6 +475,50 @@ definitions:
|
|||||||
output:
|
output:
|
||||||
type: string
|
type: string
|
||||||
x-go-name: Output
|
x-go-name: Output
|
||||||
|
rotation:
|
||||||
|
$ref: '#/definitions/LogRotationConfig'
|
||||||
|
type: object
|
||||||
|
x-go-package: github.com/go-gost/x/config
|
||||||
|
LogRotationConfig:
|
||||||
|
properties:
|
||||||
|
compress:
|
||||||
|
description: |-
|
||||||
|
Compress determines if the rotated log files should be compressed
|
||||||
|
using gzip. The default is not to perform compression.
|
||||||
|
type: boolean
|
||||||
|
x-go-name: Compress
|
||||||
|
localTime:
|
||||||
|
description: |-
|
||||||
|
LocalTime determines if the time used for formatting the timestamps in
|
||||||
|
backup files is the computer's local time. The default is to use UTC
|
||||||
|
time.
|
||||||
|
type: boolean
|
||||||
|
x-go-name: LocalTime
|
||||||
|
maxAge:
|
||||||
|
description: |-
|
||||||
|
MaxAge is the maximum number of days to retain old log files based on the
|
||||||
|
timestamp encoded in their filename. Note that a day is defined as 24
|
||||||
|
hours and may not exactly correspond to calendar days due to daylight
|
||||||
|
savings, leap seconds, etc. The default is not to remove old log files
|
||||||
|
based on age.
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
x-go-name: MaxAge
|
||||||
|
maxBackups:
|
||||||
|
description: |-
|
||||||
|
MaxBackups is the maximum number of old log files to retain. The default
|
||||||
|
is to retain all old log files (though MaxAge may still cause them to get
|
||||||
|
deleted.)
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
x-go-name: MaxBackups
|
||||||
|
maxSize:
|
||||||
|
description: |-
|
||||||
|
MaxSize is the maximum size in megabytes of the log file before it gets
|
||||||
|
rotated. It defaults to 100 megabytes.
|
||||||
|
format: int64
|
||||||
|
type: integer
|
||||||
|
x-go-name: MaxSize
|
||||||
type: object
|
type: object
|
||||||
x-go-package: github.com/go-gost/x/config
|
x-go-package: github.com/go-gost/x/config
|
||||||
MetricsConfig:
|
MetricsConfig:
|
||||||
@ -521,6 +571,9 @@ definitions:
|
|||||||
$ref: '#/definitions/ConnectorConfig'
|
$ref: '#/definitions/ConnectorConfig'
|
||||||
dialer:
|
dialer:
|
||||||
$ref: '#/definitions/DialerConfig'
|
$ref: '#/definitions/DialerConfig'
|
||||||
|
host:
|
||||||
|
type: string
|
||||||
|
x-go-name: Host
|
||||||
hosts:
|
hosts:
|
||||||
type: string
|
type: string
|
||||||
x-go-name: Hosts
|
x-go-name: Hosts
|
||||||
@ -534,6 +587,9 @@ definitions:
|
|||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
x-go-name: Name
|
x-go-name: Name
|
||||||
|
protocol:
|
||||||
|
type: string
|
||||||
|
x-go-name: Protocol
|
||||||
resolver:
|
resolver:
|
||||||
type: string
|
type: string
|
||||||
x-go-name: Resolver
|
x-go-name: Resolver
|
||||||
|
@ -339,6 +339,12 @@ func ParseRecorder(cfg *config.RecorderConfig) (r recorder.Recorder) {
|
|||||||
xrecorder.KeyRedisRecorderOption(cfg.Redis.Key),
|
xrecorder.KeyRedisRecorderOption(cfg.Redis.Key),
|
||||||
xrecorder.PasswordRedisRecorderOption(cfg.Redis.Password),
|
xrecorder.PasswordRedisRecorderOption(cfg.Redis.Password),
|
||||||
)
|
)
|
||||||
|
case "sset": // sorted set
|
||||||
|
return xrecorder.RedisSortedSetRecorder(cfg.Redis.Addr,
|
||||||
|
xrecorder.DBRedisRecorderOption(cfg.Redis.DB),
|
||||||
|
xrecorder.KeyRedisRecorderOption(cfg.Redis.Key),
|
||||||
|
xrecorder.PasswordRedisRecorderOption(cfg.Redis.Password),
|
||||||
|
)
|
||||||
default: // redis set
|
default: // redis set
|
||||||
return xrecorder.RedisSetRecorder(cfg.Redis.Addr,
|
return xrecorder.RedisSetRecorder(cfg.Redis.Addr,
|
||||||
xrecorder.DBRedisRecorderOption(cfg.Redis.DB),
|
xrecorder.DBRedisRecorderOption(cfg.Redis.DB),
|
||||||
|
@ -66,6 +66,7 @@ func (c *conn) Close() error {
|
|||||||
case <-c.closed:
|
case <-c.closed:
|
||||||
default:
|
default:
|
||||||
close(c.closed)
|
close(c.closed)
|
||||||
|
return c.c.CloseSend()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/go-gost/core/dialer"
|
"github.com/go-gost/core/dialer"
|
||||||
md "github.com/go-gost/core/metadata"
|
md "github.com/go-gost/core/metadata"
|
||||||
@ -14,6 +13,7 @@ import (
|
|||||||
"google.golang.org/grpc/backoff"
|
"google.golang.org/grpc/backoff"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
"google.golang.org/grpc/credentials/insecure"
|
||||||
|
"google.golang.org/grpc/keepalive"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -82,7 +82,7 @@ func (d *grpcDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO
|
|||||||
grpc.WithAuthority(host),
|
grpc.WithAuthority(host),
|
||||||
grpc.WithConnectParams(grpc.ConnectParams{
|
grpc.WithConnectParams(grpc.ConnectParams{
|
||||||
Backoff: backoff.DefaultConfig,
|
Backoff: backoff.DefaultConfig,
|
||||||
MinConnectTimeout: 10 * time.Second,
|
MinConnectTimeout: d.md.minConnectTimeout,
|
||||||
}),
|
}),
|
||||||
grpc.FailOnNonTempDialError(true),
|
grpc.FailOnNonTempDialError(true),
|
||||||
}
|
}
|
||||||
@ -92,6 +92,14 @@ func (d *grpcDialer) Dial(ctx context.Context, addr string, opts ...dialer.DialO
|
|||||||
grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
grpcOpts = append(grpcOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if d.md.keepalive {
|
||||||
|
grpcOpts = append(grpcOpts, grpc.WithKeepaliveParams(keepalive.ClientParameters{
|
||||||
|
Time: d.md.keepaliveTime,
|
||||||
|
Timeout: d.md.keepaliveTimeout,
|
||||||
|
PermitWithoutStream: d.md.keepalivePermitWithoutStream,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
cc, err := grpc.DialContext(ctx, addr, grpcOpts...)
|
cc, err := grpc.DialContext(ctx, addr, grpcOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
d.options.Logger.Error(err)
|
d.options.Logger.Error(err)
|
||||||
|
@ -1,26 +1,43 @@
|
|||||||
package grpc
|
package grpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
mdata "github.com/go-gost/core/metadata"
|
mdata "github.com/go-gost/core/metadata"
|
||||||
mdutil "github.com/go-gost/core/metadata/util"
|
mdutil "github.com/go-gost/core/metadata/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
insecure bool
|
insecure bool
|
||||||
host string
|
host string
|
||||||
path string
|
path string
|
||||||
|
keepalive bool
|
||||||
|
keepaliveTime time.Duration
|
||||||
|
keepaliveTimeout time.Duration
|
||||||
|
keepalivePermitWithoutStream bool
|
||||||
|
minConnectTimeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *grpcDialer) parseMetadata(md mdata.Metadata) (err error) {
|
func (d *grpcDialer) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
d.md.insecure = mdutil.GetBool(md, "grpc.insecure", "grpcInsecure", "insecure")
|
||||||
insecure = "grpcInsecure"
|
d.md.host = mdutil.GetString(md, "grpc.authority", "grpc.host", "host")
|
||||||
host = "host"
|
d.md.path = mdutil.GetString(md, "grpc.path", "path")
|
||||||
path = "path"
|
d.md.keepalive = mdutil.GetBool(md, "grpc.keepalive", "keepalive", "keepAlive")
|
||||||
)
|
if d.md.keepalive {
|
||||||
|
d.md.keepaliveTime = mdutil.GetDuration(md, "grpc.keepalive.time", "keepalive.time")
|
||||||
d.md.insecure = mdutil.GetBool(md, insecure)
|
if d.md.keepaliveTime <= 0 {
|
||||||
d.md.host = mdutil.GetString(md, host)
|
d.md.keepaliveTime = 30 * time.Second
|
||||||
d.md.path = mdutil.GetString(md, path)
|
}
|
||||||
|
d.md.keepaliveTimeout = mdutil.GetDuration(md, "grpc.keepalive.timeout", "keepalive.timeout")
|
||||||
|
if d.md.keepaliveTimeout <= 0 {
|
||||||
|
d.md.keepaliveTimeout = 30 * time.Second
|
||||||
|
}
|
||||||
|
d.md.keepalivePermitWithoutStream = mdutil.GetBool(md, "grpc.keepalive.permitWithoutStream", "keepalive.permitWithoutStream")
|
||||||
|
}
|
||||||
|
d.md.minConnectTimeout = mdutil.GetDuration(md, "grpc.minConnectTimeout", "minConnectTimeout")
|
||||||
|
if d.md.minConnectTimeout <= 0 {
|
||||||
|
d.md.minConnectTimeout = 30 * time.Second
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -22,42 +21,6 @@ const (
|
|||||||
IPLimitKey = "$$"
|
IPLimitKey = "$$"
|
||||||
)
|
)
|
||||||
|
|
||||||
type limiterGroup struct {
|
|
||||||
limiters []limiter.Limiter
|
|
||||||
}
|
|
||||||
|
|
||||||
func newLimiterGroup(limiters ...limiter.Limiter) *limiterGroup {
|
|
||||||
sort.Slice(limiters, func(i, j int) bool {
|
|
||||||
return limiters[i].Limit() < limiters[j].Limit()
|
|
||||||
})
|
|
||||||
return &limiterGroup{limiters: limiters}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *limiterGroup) Allow(n int) (b bool) {
|
|
||||||
var i int
|
|
||||||
|
|
||||||
for i = range l.limiters {
|
|
||||||
if b = l.limiters[i].Allow(n); !b {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !b && i > 0 && n > 0 {
|
|
||||||
for i := range l.limiters[:i] {
|
|
||||||
l.limiters[i].Allow(-n)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *limiterGroup) Limit() int {
|
|
||||||
if len(l.limiters) == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return l.limiters[0].Limit()
|
|
||||||
}
|
|
||||||
|
|
||||||
type options struct {
|
type options struct {
|
||||||
limits []string
|
limits []string
|
||||||
fileLoader loader.Loader
|
fileLoader loader.Loader
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package conn
|
package conn
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sort"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
limiter "github.com/go-gost/core/limiter/conn"
|
limiter "github.com/go-gost/core/limiter/conn"
|
||||||
@ -28,3 +29,39 @@ func (l *llimiter) Allow(n int) bool {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type limiterGroup struct {
|
||||||
|
limiters []limiter.Limiter
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLimiterGroup(limiters ...limiter.Limiter) *limiterGroup {
|
||||||
|
sort.Slice(limiters, func(i, j int) bool {
|
||||||
|
return limiters[i].Limit() < limiters[j].Limit()
|
||||||
|
})
|
||||||
|
return &limiterGroup{limiters: limiters}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *limiterGroup) Allow(n int) (b bool) {
|
||||||
|
var i int
|
||||||
|
|
||||||
|
for i = range l.limiters {
|
||||||
|
if b = l.limiters[i].Allow(n); !b {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !b && i > 0 && n > 0 {
|
||||||
|
for i := range l.limiters[:i] {
|
||||||
|
l.limiters[i].Allow(-n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *limiterGroup) Limit() int {
|
||||||
|
if len(l.limiters) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.limiters[0].Limit()
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package rate
|
package rate
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
limiter "github.com/go-gost/core/limiter/rate"
|
limiter "github.com/go-gost/core/limiter/rate"
|
||||||
@ -24,3 +25,32 @@ func (l *rlimiter) Allow(n int) bool {
|
|||||||
func (l *rlimiter) Limit() float64 {
|
func (l *rlimiter) Limit() float64 {
|
||||||
return float64(l.limiter.Limit())
|
return float64(l.limiter.Limit())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type limiterGroup struct {
|
||||||
|
limiters []limiter.Limiter
|
||||||
|
}
|
||||||
|
|
||||||
|
func newLimiterGroup(limiters ...limiter.Limiter) *limiterGroup {
|
||||||
|
sort.Slice(limiters, func(i, j int) bool {
|
||||||
|
return limiters[i].Limit() < limiters[j].Limit()
|
||||||
|
})
|
||||||
|
return &limiterGroup{limiters: limiters}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *limiterGroup) Allow(n int) (b bool) {
|
||||||
|
b = true
|
||||||
|
for i := range l.limiters {
|
||||||
|
if v := l.limiters[i].Allow(n); !v {
|
||||||
|
b = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *limiterGroup) Limit() float64 {
|
||||||
|
if len(l.limiters) == 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return l.limiters[0].Limit()
|
||||||
|
}
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -22,35 +21,6 @@ const (
|
|||||||
IPLimitKey = "$$"
|
IPLimitKey = "$$"
|
||||||
)
|
)
|
||||||
|
|
||||||
type limiterGroup struct {
|
|
||||||
limiters []limiter.Limiter
|
|
||||||
}
|
|
||||||
|
|
||||||
func newLimiterGroup(limiters ...limiter.Limiter) *limiterGroup {
|
|
||||||
sort.Slice(limiters, func(i, j int) bool {
|
|
||||||
return limiters[i].Limit() < limiters[j].Limit()
|
|
||||||
})
|
|
||||||
return &limiterGroup{limiters: limiters}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *limiterGroup) Allow(n int) (b bool) {
|
|
||||||
b = true
|
|
||||||
for i := range l.limiters {
|
|
||||||
if v := l.limiters[i].Allow(n); !v {
|
|
||||||
b = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *limiterGroup) Limit() float64 {
|
|
||||||
if len(l.limiters) == 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return l.limiters[0].Limit()
|
|
||||||
}
|
|
||||||
|
|
||||||
type options struct {
|
type options struct {
|
||||||
limits []string
|
limits []string
|
||||||
fileLoader loader.Loader
|
fileLoader loader.Loader
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/go-gost/x/registry"
|
"github.com/go-gost/x/registry"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/credentials"
|
"google.golang.org/grpc/credentials"
|
||||||
|
"google.golang.org/grpc/keepalive"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -67,6 +68,19 @@ func (l *grpcListener) Init(md md.Metadata) (err error) {
|
|||||||
if !l.md.insecure {
|
if !l.md.insecure {
|
||||||
opts = append(opts, grpc.Creds(credentials.NewTLS(l.options.TLSConfig)))
|
opts = append(opts, grpc.Creds(credentials.NewTLS(l.options.TLSConfig)))
|
||||||
}
|
}
|
||||||
|
if l.md.keepalive {
|
||||||
|
opts = append(opts,
|
||||||
|
grpc.KeepaliveEnforcementPolicy(keepalive.EnforcementPolicy{
|
||||||
|
MinTime: l.md.keepaliveMinTime,
|
||||||
|
PermitWithoutStream: l.md.keepalivePermitWithoutStream,
|
||||||
|
}),
|
||||||
|
grpc.KeepaliveParams(keepalive.ServerParameters{
|
||||||
|
MaxConnectionIdle: l.md.keepaliveMaxConnectionIdle,
|
||||||
|
Time: l.md.keepaliveTime,
|
||||||
|
Timeout: l.md.keepaliveTimeout,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
l.server = grpc.NewServer(opts...)
|
l.server = grpc.NewServer(opts...)
|
||||||
l.addr = ln.Addr()
|
l.addr = ln.Addr()
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package grpc
|
package grpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
mdata "github.com/go-gost/core/metadata"
|
mdata "github.com/go-gost/core/metadata"
|
||||||
mdutil "github.com/go-gost/core/metadata/util"
|
mdutil "github.com/go-gost/core/metadata/util"
|
||||||
)
|
)
|
||||||
@ -10,24 +12,44 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type metadata struct {
|
type metadata struct {
|
||||||
backlog int
|
backlog int
|
||||||
insecure bool
|
insecure bool
|
||||||
path string
|
path string
|
||||||
|
keepalive bool
|
||||||
|
keepaliveMinTime time.Duration
|
||||||
|
keepaliveTime time.Duration
|
||||||
|
keepaliveTimeout time.Duration
|
||||||
|
keepalivePermitWithoutStream bool
|
||||||
|
keepaliveMaxConnectionIdle time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *grpcListener) parseMetadata(md mdata.Metadata) (err error) {
|
func (l *grpcListener) parseMetadata(md mdata.Metadata) (err error) {
|
||||||
const (
|
l.md.backlog = mdutil.GetInt(md, "grpc.backlog", "backlog")
|
||||||
backlog = "backlog"
|
|
||||||
insecure = "grpcInsecure"
|
|
||||||
path = "path"
|
|
||||||
)
|
|
||||||
|
|
||||||
l.md.backlog = mdutil.GetInt(md, backlog)
|
|
||||||
if l.md.backlog <= 0 {
|
if l.md.backlog <= 0 {
|
||||||
l.md.backlog = defaultBacklog
|
l.md.backlog = defaultBacklog
|
||||||
}
|
}
|
||||||
|
|
||||||
l.md.insecure = mdutil.GetBool(md, insecure)
|
l.md.insecure = mdutil.GetBool(md, "grpc.insecure", "grpcInsecure", "insecure")
|
||||||
l.md.path = mdutil.GetString(md, path)
|
l.md.path = mdutil.GetString(md, "grpc.path", "path")
|
||||||
|
|
||||||
|
l.md.keepalive = mdutil.GetBool(md, "grpc.keepalive", "keepalive", "keepAlive")
|
||||||
|
if l.md.keepalive {
|
||||||
|
l.md.keepaliveMinTime = mdutil.GetDuration(md, "grpc.keepalive.minTime", "keepalive.minTime")
|
||||||
|
if l.md.keepaliveMinTime <= 0 {
|
||||||
|
l.md.keepaliveMinTime = 30 * time.Second
|
||||||
|
}
|
||||||
|
l.md.keepaliveTime = mdutil.GetDuration(md, "grpc.keepalive.time", "keepalive.time")
|
||||||
|
if l.md.keepaliveTime <= 0 {
|
||||||
|
l.md.keepaliveTime = 60 * time.Second
|
||||||
|
}
|
||||||
|
l.md.keepaliveTimeout = mdutil.GetDuration(md, "grpc.keepalive.timeout", "keepalive.timeout")
|
||||||
|
if l.md.keepaliveTimeout <= 0 {
|
||||||
|
l.md.keepaliveTimeout = 30 * time.Second
|
||||||
|
}
|
||||||
|
|
||||||
|
l.md.keepalivePermitWithoutStream = mdutil.GetBool(md, "grpc.keepalive.permitWithoutStream", "keepalive.permitWithoutStream")
|
||||||
|
l.md.keepaliveMaxConnectionIdle = mdutil.GetDuration(md, "grpc.keepalive.maxConnectionIdle", "keepalive.maxConnectionIdle")
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -99,3 +99,40 @@ func (r *redisListRecorder) Record(ctx context.Context, b []byte) error {
|
|||||||
func (r *redisListRecorder) Close() error {
|
func (r *redisListRecorder) Close() error {
|
||||||
return r.client.Close()
|
return r.client.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type redisSortedSetRecorder struct {
|
||||||
|
client *redis.Client
|
||||||
|
key string
|
||||||
|
}
|
||||||
|
|
||||||
|
// RedisSortedSetRecorder records data to a redis sorted set.
|
||||||
|
func RedisSortedSetRecorder(addr string, opts ...RedisRecorderOption) recorder.Recorder {
|
||||||
|
var options redisRecorderOptions
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(&options)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &redisSortedSetRecorder{
|
||||||
|
client: redis.NewClient(&redis.Options{
|
||||||
|
Addr: addr,
|
||||||
|
Password: options.password,
|
||||||
|
DB: options.db,
|
||||||
|
}),
|
||||||
|
key: options.key,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *redisSortedSetRecorder) Record(ctx context.Context, b []byte) error {
|
||||||
|
if r.key == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.client.ZIncr(ctx, r.key, &redis.Z{
|
||||||
|
Score: 1,
|
||||||
|
Member: b,
|
||||||
|
}).Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *redisSortedSetRecorder) Close() error {
|
||||||
|
return r.client.Close()
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user