|
|
@ -14,12 +14,12 @@ import ( |
|
|
|
"github.com/bilibili/kratos/pkg/conf/flagvar" |
|
|
|
"github.com/bilibili/kratos/pkg/conf/flagvar" |
|
|
|
"github.com/bilibili/kratos/pkg/ecode" |
|
|
|
"github.com/bilibili/kratos/pkg/ecode" |
|
|
|
"github.com/bilibili/kratos/pkg/naming" |
|
|
|
"github.com/bilibili/kratos/pkg/naming" |
|
|
|
|
|
|
|
"github.com/bilibili/kratos/pkg/naming/discovery" |
|
|
|
nmd "github.com/bilibili/kratos/pkg/net/metadata" |
|
|
|
nmd "github.com/bilibili/kratos/pkg/net/metadata" |
|
|
|
"github.com/bilibili/kratos/pkg/net/netutil/breaker" |
|
|
|
"github.com/bilibili/kratos/pkg/net/netutil/breaker" |
|
|
|
"github.com/bilibili/kratos/pkg/net/rpc/warden/balancer/p2c" |
|
|
|
"github.com/bilibili/kratos/pkg/net/rpc/warden/balancer/p2c" |
|
|
|
"github.com/bilibili/kratos/pkg/net/rpc/warden/internal/status" |
|
|
|
"github.com/bilibili/kratos/pkg/net/rpc/warden/internal/status" |
|
|
|
"github.com/bilibili/kratos/pkg/net/rpc/warden/resolver" |
|
|
|
"github.com/bilibili/kratos/pkg/net/rpc/warden/resolver" |
|
|
|
"github.com/bilibili/kratos/pkg/net/rpc/warden/resolver/direct" |
|
|
|
|
|
|
|
"github.com/bilibili/kratos/pkg/net/trace" |
|
|
|
"github.com/bilibili/kratos/pkg/net/trace" |
|
|
|
xtime "github.com/bilibili/kratos/pkg/time" |
|
|
|
xtime "github.com/bilibili/kratos/pkg/time" |
|
|
|
|
|
|
|
|
|
|
@ -51,10 +51,6 @@ func baseMetadata() metadata.MD { |
|
|
|
return gmd |
|
|
|
return gmd |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func init() { |
|
|
|
|
|
|
|
resolver.Register(direct.New()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ClientConfig is rpc client conf.
|
|
|
|
// ClientConfig is rpc client conf.
|
|
|
|
type ClientConfig struct { |
|
|
|
type ClientConfig struct { |
|
|
|
Dial xtime.Duration |
|
|
|
Dial xtime.Duration |
|
|
@ -74,7 +70,7 @@ type Client struct { |
|
|
|
breaker *breaker.Group |
|
|
|
breaker *breaker.Group |
|
|
|
mutex sync.RWMutex |
|
|
|
mutex sync.RWMutex |
|
|
|
|
|
|
|
|
|
|
|
opt []grpc.DialOption |
|
|
|
opts []grpc.DialOption |
|
|
|
handlers []grpc.UnaryClientInterceptor |
|
|
|
handlers []grpc.UnaryClientInterceptor |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -160,19 +156,20 @@ func NewConn(target string, opt ...grpc.DialOption) (*grpc.ClientConn, error) { |
|
|
|
// NewClient returns a new blank Client instance with a default client interceptor.
|
|
|
|
// NewClient returns a new blank Client instance with a default client interceptor.
|
|
|
|
// opt can be used to add grpc dial options.
|
|
|
|
// opt can be used to add grpc dial options.
|
|
|
|
func NewClient(conf *ClientConfig, opt ...grpc.DialOption) *Client { |
|
|
|
func NewClient(conf *ClientConfig, opt ...grpc.DialOption) *Client { |
|
|
|
|
|
|
|
resolver.Register(discovery.Builder()) |
|
|
|
c := new(Client) |
|
|
|
c := new(Client) |
|
|
|
if err := c.SetConfig(conf); err != nil { |
|
|
|
if err := c.SetConfig(conf); err != nil { |
|
|
|
panic(err) |
|
|
|
panic(err) |
|
|
|
} |
|
|
|
} |
|
|
|
c.UseOpt(grpc.WithBalancerName(p2c.Name)) |
|
|
|
c.UseOpt(grpc.WithBalancerName(p2c.Name)) |
|
|
|
c.UseOpt(opt...) |
|
|
|
c.UseOpt(opt...) |
|
|
|
c.Use(c.recovery(), clientLogging(), c.handle()) |
|
|
|
|
|
|
|
return c |
|
|
|
return c |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// DefaultClient returns a new default Client instance with a default client interceptor and default dialoption.
|
|
|
|
// DefaultClient returns a new default Client instance with a default client interceptor and default dialoption.
|
|
|
|
// opt can be used to add grpc dial options.
|
|
|
|
// opt can be used to add grpc dial options.
|
|
|
|
func DefaultClient() *Client { |
|
|
|
func DefaultClient() *Client { |
|
|
|
|
|
|
|
resolver.Register(discovery.Builder()) |
|
|
|
_once.Do(func() { |
|
|
|
_once.Do(func() { |
|
|
|
_defaultClient = NewClient(nil) |
|
|
|
_defaultClient = NewClient(nil) |
|
|
|
}) |
|
|
|
}) |
|
|
@ -221,21 +218,33 @@ func (c *Client) Use(handlers ...grpc.UnaryClientInterceptor) *Client { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// UseOpt attachs a global grpc DialOption to the Client.
|
|
|
|
// UseOpt attachs a global grpc DialOption to the Client.
|
|
|
|
func (c *Client) UseOpt(opt ...grpc.DialOption) *Client { |
|
|
|
func (c *Client) UseOpt(opts ...grpc.DialOption) *Client { |
|
|
|
c.opt = append(c.opt, opt...) |
|
|
|
c.opts = append(c.opts, opts...) |
|
|
|
return c |
|
|
|
return c |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Dial creates a client connection to the given target.
|
|
|
|
func (c *Client) cloneOpts() []grpc.DialOption { |
|
|
|
// Target format is scheme://authority/endpoint?query_arg=value
|
|
|
|
dialOptions := make([]grpc.DialOption, len(c.opts)) |
|
|
|
// example: direct://default/192.168.1.1:9000,192.168.1.2:9001
|
|
|
|
copy(dialOptions, c.opts) |
|
|
|
func (c *Client) Dial(ctx context.Context, target string, opt ...grpc.DialOption) (conn *grpc.ClientConn, err error) { |
|
|
|
return dialOptions |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (c *Client) dial(ctx context.Context, target string, opts ...grpc.DialOption) (conn *grpc.ClientConn, err error) { |
|
|
|
|
|
|
|
dialOptions := c.cloneOpts() |
|
|
|
if !c.conf.NonBlock { |
|
|
|
if !c.conf.NonBlock { |
|
|
|
c.opt = append(c.opt, grpc.WithBlock()) |
|
|
|
dialOptions = append(dialOptions, grpc.WithBlock()) |
|
|
|
} |
|
|
|
} |
|
|
|
c.opt = append(c.opt, grpc.WithInsecure()) |
|
|
|
dialOptions = append(dialOptions, opts...) |
|
|
|
c.opt = append(c.opt, grpc.WithUnaryInterceptor(c.chainUnaryClient())) |
|
|
|
|
|
|
|
c.opt = append(c.opt, opt...) |
|
|
|
// init default handler
|
|
|
|
|
|
|
|
var handlers []grpc.UnaryClientInterceptor |
|
|
|
|
|
|
|
handlers = append(handlers, c.recovery()) |
|
|
|
|
|
|
|
handlers = append(handlers, clientLogging(dialOptions...)) |
|
|
|
|
|
|
|
handlers = append(handlers, c.handlers...) |
|
|
|
|
|
|
|
// NOTE: c.handle must be a last interceptor.
|
|
|
|
|
|
|
|
handlers = append(handlers, c.handle()) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dialOptions = append(dialOptions, grpc.WithUnaryInterceptor(chainUnaryClient(handlers))) |
|
|
|
c.mutex.RLock() |
|
|
|
c.mutex.RLock() |
|
|
|
conf := c.conf |
|
|
|
conf := c.conf |
|
|
|
c.mutex.RUnlock() |
|
|
|
c.mutex.RUnlock() |
|
|
@ -268,43 +277,39 @@ func (c *Client) Dial(ctx context.Context, target string, opt ...grpc.DialOption |
|
|
|
} |
|
|
|
} |
|
|
|
target = u.String() |
|
|
|
target = u.String() |
|
|
|
} |
|
|
|
} |
|
|
|
if conn, err = grpc.DialContext(ctx, target, c.opt...); err != nil { |
|
|
|
if conn, err = grpc.DialContext(ctx, target, dialOptions...); err != nil { |
|
|
|
fmt.Fprintf(os.Stderr, "warden client: dial %s error %v!", target, err) |
|
|
|
fmt.Fprintf(os.Stderr, "warden client: dial %s error %v!", target, err) |
|
|
|
} |
|
|
|
} |
|
|
|
err = errors.WithStack(err) |
|
|
|
err = errors.WithStack(err) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Dial creates a client connection to the given target.
|
|
|
|
|
|
|
|
// Target format is scheme://authority/endpoint?query_arg=value
|
|
|
|
|
|
|
|
// example: discovery://default/account.account.service?cluster=shfy01&cluster=shfy02
|
|
|
|
|
|
|
|
func (c *Client) Dial(ctx context.Context, target string, opts ...grpc.DialOption) (conn *grpc.ClientConn, err error) { |
|
|
|
|
|
|
|
opts = append(opts, grpc.WithInsecure()) |
|
|
|
|
|
|
|
return c.dial(ctx, target, opts...) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// DialTLS creates a client connection over tls transport to the given target.
|
|
|
|
// DialTLS creates a client connection over tls transport to the given target.
|
|
|
|
func (c *Client) DialTLS(ctx context.Context, target string, file string, name string) (conn *grpc.ClientConn, err error) { |
|
|
|
func (c *Client) DialTLS(ctx context.Context, target string, file string, name string, opts ...grpc.DialOption) (conn *grpc.ClientConn, err error) { |
|
|
|
var creds credentials.TransportCredentials |
|
|
|
var creds credentials.TransportCredentials |
|
|
|
creds, err = credentials.NewClientTLSFromFile(file, name) |
|
|
|
creds, err = credentials.NewClientTLSFromFile(file, name) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
err = errors.WithStack(err) |
|
|
|
err = errors.WithStack(err) |
|
|
|
return |
|
|
|
return |
|
|
|
} |
|
|
|
} |
|
|
|
c.opt = append(c.opt, grpc.WithBlock()) |
|
|
|
opts = append(opts, grpc.WithTransportCredentials(creds)) |
|
|
|
c.opt = append(c.opt, grpc.WithTransportCredentials(creds)) |
|
|
|
return c.dial(ctx, target, opts...) |
|
|
|
c.opt = append(c.opt, grpc.WithUnaryInterceptor(c.chainUnaryClient())) |
|
|
|
|
|
|
|
c.mutex.RLock() |
|
|
|
|
|
|
|
conf := c.conf |
|
|
|
|
|
|
|
c.mutex.RUnlock() |
|
|
|
|
|
|
|
if conf.Dial > 0 { |
|
|
|
|
|
|
|
var cancel context.CancelFunc |
|
|
|
|
|
|
|
ctx, cancel = context.WithTimeout(ctx, time.Duration(conf.Dial)) |
|
|
|
|
|
|
|
defer cancel() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
conn, err = grpc.DialContext(ctx, target, c.opt...) |
|
|
|
|
|
|
|
err = errors.WithStack(err) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// chainUnaryClient creates a single interceptor out of a chain of many interceptors.
|
|
|
|
// chainUnaryClient creates a single interceptor out of a chain of many interceptors.
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Execution is done in left-to-right order, including passing of context.
|
|
|
|
// Execution is done in left-to-right order, including passing of context.
|
|
|
|
// For example ChainUnaryClient(one, two, three) will execute one before two before three.
|
|
|
|
// For example ChainUnaryClient(one, two, three) will execute one before two before three.
|
|
|
|
func (c *Client) chainUnaryClient() grpc.UnaryClientInterceptor { |
|
|
|
func chainUnaryClient(handlers []grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor { |
|
|
|
n := len(c.handlers) |
|
|
|
n := len(handlers) |
|
|
|
if n == 0 { |
|
|
|
if n == 0 { |
|
|
|
return func(ctx context.Context, method string, req, reply interface{}, |
|
|
|
return func(ctx context.Context, method string, req, reply interface{}, |
|
|
|
cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { |
|
|
|
cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { |
|
|
@ -323,9 +328,9 @@ func (c *Client) chainUnaryClient() grpc.UnaryClientInterceptor { |
|
|
|
return invoker(ictx, imethod, ireq, ireply, ic, iopts...) |
|
|
|
return invoker(ictx, imethod, ireq, ireply, ic, iopts...) |
|
|
|
} |
|
|
|
} |
|
|
|
i++ |
|
|
|
i++ |
|
|
|
return c.handlers[i](ictx, imethod, ireq, ireply, ic, chainHandler, iopts...) |
|
|
|
return handlers[i](ictx, imethod, ireq, ireply, ic, chainHandler, iopts...) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return c.handlers[0](ctx, method, req, reply, cc, chainHandler, opts...) |
|
|
|
return handlers[0](ctx, method, req, reply, cc, chainHandler, opts...) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|