fix(transport/http): fixed the problem of getting empty node list (#1206)

* fix(transport/http): fixed the problem of getting empty node list

* fix http blocking

Co-authored-by: longXboy <longxboyhi@gmail.com>
pull/1207/head
包子 3 years ago committed by GitHub
parent b2ba585b2e
commit 5f678de2cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 24
      examples/registry/etcd/client/main.go
  2. 11
      examples/registry/etcd/server/main.go
  3. 10
      transport/http/client.go
  4. 31
      transport/http/resolver.go

@ -7,6 +7,7 @@ import (
"github.com/go-kratos/etcd/registry" "github.com/go-kratos/etcd/registry"
"github.com/go-kratos/kratos/examples/helloworld/helloworld" "github.com/go-kratos/kratos/examples/helloworld/helloworld"
"github.com/go-kratos/kratos/v2/transport/grpc" "github.com/go-kratos/kratos/v2/transport/grpc"
"github.com/go-kratos/kratos/v2/transport/http"
clientv3 "go.etcd.io/etcd/client/v3" clientv3 "go.etcd.io/etcd/client/v3"
) )
@ -18,6 +19,11 @@ func main() {
panic(err) panic(err)
} }
r := registry.New(cli) r := registry.New(cli)
callGRPC(r)
callHTTP(r)
}
func callGRPC(r *registry.Registry) {
conn, err := grpc.DialInsecure( conn, err := grpc.DialInsecure(
context.Background(), context.Background(),
grpc.WithEndpoint("discovery:///helloworld"), grpc.WithEndpoint("discovery:///helloworld"),
@ -33,3 +39,21 @@ func main() {
} }
log.Printf("[grpc] SayHello %+v\n", reply) log.Printf("[grpc] SayHello %+v\n", reply)
} }
func callHTTP(r *registry.Registry) {
conn, err := http.NewClient(
context.Background(),
http.WithEndpoint("discovery:///helloworld"),
http.WithDiscovery(r),
http.WithBlock(),
)
if err != nil {
log.Fatal(err)
}
client := helloworld.NewGreeterHTTPClient(conn)
reply, err := client.SayHello(context.Background(), &helloworld.HelloRequest{Name: "kratos"})
if err != nil {
log.Fatal(err)
}
log.Printf("[http] SayHello %+v\n", reply)
}

@ -8,7 +8,9 @@ import (
"github.com/go-kratos/etcd/registry" "github.com/go-kratos/etcd/registry"
pb "github.com/go-kratos/kratos/examples/helloworld/helloworld" pb "github.com/go-kratos/kratos/examples/helloworld/helloworld"
"github.com/go-kratos/kratos/v2" "github.com/go-kratos/kratos/v2"
"github.com/go-kratos/kratos/v2/middleware/recovery"
"github.com/go-kratos/kratos/v2/transport/grpc" "github.com/go-kratos/kratos/v2/transport/grpc"
"github.com/go-kratos/kratos/v2/transport/http"
etcd "go.etcd.io/etcd/client/v3" etcd "go.etcd.io/etcd/client/v3"
) )
@ -34,13 +36,20 @@ func main() {
grpcSrv := grpc.NewServer( grpcSrv := grpc.NewServer(
grpc.Address(":9000"), grpc.Address(":9000"),
) )
httpSrv := http.NewServer(
http.Address(":8000"),
http.Middleware(
recovery.Recovery(),
),
)
s := &server{} s := &server{}
pb.RegisterGreeterServer(grpcSrv, s) pb.RegisterGreeterServer(grpcSrv, s)
pb.RegisterGreeterHTTPServer(httpSrv, s)
app := kratos.New( app := kratos.New(
kratos.Name("helloworld"), kratos.Name("helloworld"),
kratos.Server( kratos.Server(
grpcSrv, grpcSrv,
httpSrv,
), ),
kratos.Registrar(r), kratos.Registrar(r),
) )

@ -45,6 +45,7 @@ type clientOptions struct {
balancer balancer.Balancer balancer balancer.Balancer
discovery registry.Discovery discovery registry.Discovery
middleware []middleware.Middleware middleware []middleware.Middleware
block bool
} }
// WithTransport with client transport. // WithTransport with client transport.
@ -119,6 +120,13 @@ func WithBalancer(b balancer.Balancer) ClientOption {
} }
} }
// WithBlock with client block.
func WithBlock() ClientOption {
return func(o *clientOptions) {
o.block = true
}
}
// Client is an HTTP client. // Client is an HTTP client.
type Client struct { type Client struct {
opts clientOptions opts clientOptions
@ -148,7 +156,7 @@ func NewClient(ctx context.Context, opts ...ClientOption) (*Client, error) {
var r *resolver var r *resolver
if options.discovery != nil { if options.discovery != nil {
if target.Scheme == "discovery" { if target.Scheme == "discovery" {
if r, err = newResolver(ctx, options.discovery, target, options.balancer); err != nil { if r, err = newResolver(ctx, options.discovery, target, options.balancer, options.block); err != nil {
return nil, fmt.Errorf("[http client] new resolver failed!err: %v", options.endpoint) return nil, fmt.Errorf("[http client] new resolver failed!err: %v", options.endpoint)
} }
} else if _, _, err := host.ExtractHostPort(options.endpoint); err != nil { } else if _, _, err := host.ExtractHostPort(options.endpoint); err != nil {

@ -44,7 +44,7 @@ type resolver struct {
logger *log.Helper logger *log.Helper
} }
func newResolver(ctx context.Context, discovery registry.Discovery, target *Target, updater Updater) (*resolver, error) { func newResolver(ctx context.Context, discovery registry.Discovery, target *Target, updater Updater, block bool) (*resolver, error) {
watcher, err := discovery.Watch(ctx, target.Endpoint) watcher, err := discovery.Watch(ctx, target.Endpoint)
if err != nil { if err != nil {
return nil, err return nil, err
@ -54,18 +54,26 @@ func newResolver(ctx context.Context, discovery registry.Discovery, target *Targ
watcher: watcher, watcher: watcher,
logger: log.NewHelper(log.DefaultLogger), logger: log.NewHelper(log.DefaultLogger),
} }
done := make(chan error, 1)
go func() { go func() {
for { for {
var executed bool
services, err := watcher.Next() services, err := watcher.Next()
if err != nil { if err != nil {
r.logger.Errorf("http client watch services got unexpected error:=%v", err) r.logger.Errorf("http client watch service %v got unexpected error:=%v", target, err)
if block {
select {
case done <- err:
default:
}
}
return return
} }
var nodes []*registry.ServiceInstance var nodes []*registry.ServiceInstance
for _, in := range services { for _, in := range services {
_, endpoint, err := parseEndpoint(in.Endpoints) _, endpoint, err := parseEndpoint(in.Endpoints)
if err != nil { if err != nil {
r.logger.Errorf("Failed to parse discovery endpoint: %v error %v", in.Endpoints, err) r.logger.Errorf("Failed to parse (%v) discovery endpoint: %v error %v", target, in.Endpoints, err)
continue continue
} }
if endpoint == "" { if endpoint == "" {
@ -79,8 +87,25 @@ func newResolver(ctx context.Context, discovery registry.Discovery, target *Targ
r.nodes = nodes r.nodes = nodes
r.lock.Unlock() r.lock.Unlock()
} }
if block && !executed {
executed = true
done <- nil
}
} }
}() }()
if block {
select {
case e := <-done:
if e != nil {
watcher.Stop()
}
return r, e
case <-ctx.Done():
r.logger.Errorf("http client watch service %v reaching context deadline!", target)
watcher.Stop()
return nil, ctx.Err()
}
}
return r, nil return r, nil
} }

Loading…
Cancel
Save