-
Notifications
You must be signed in to change notification settings - Fork 4.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DialContext will be blocked if no address exists when use a name target #976
Comments
This behavior is intentional. As the function name advises, "DialContext" should start the dialing procedure to a target. If it fails to do that (as in your case), it should return an error. I think blocking is the right behavior. If you do not want it to block your other work you can put Dial into a separate goroutine -- you can start all the processes with a blocking goroutine doing dialing. I am not clear what the architecture design is in your project. But if this is a hard requirement for your design, I would question the design ... |
Very thank you for your suggestion. we solve the problem, but i feel a little strange.As below:
the example we call the client:
2.We don't want to judge whether BizClient is nil or not before called, So we guarantee that BizClient is not a nil after function init:
3.I think dial can return a clientConn when balance strategy even if not address available, as an unblock ordinay(don't use balance) dial do. Actually, clientConn with no address allowed during execute, for example: Firstly an address avaible which make dial success, soonly the address unregistered from balancer's watcher. Why not allowd in init stage. |
I too am a bit surprised by this - would you at least consider an DialOption such that we can have a way of creating a client that is guaranteed to be non-blocking? |
I don't think this decision is consistent with other dialing behaviour of grpc-go:
The default "resolver" behaves in such a way that If you pass a host:port that is not resolvable, it will return successfully, but continually fail until the name starts to resolve, except if For a custom resolver, if I pass Default builtin "resolver": package main
import (
"log"
"os"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
)
func main() {
l := log.New(os.Stdout, "grpc: ", 0)
grpclog.SetLogger(l)
_, err := grpc.Dial("foobar.asdfasdf:1234", grpc.WithInsecure())
if err != nil {
panic(err)
}
l.Println("dialled")
select {}
} Custom resolver: package main
import (
"net"
"google.golang.org/grpc"
"google.golang.org/grpc/naming"
)
type resolver struct{}
func (r *resolver) Resolve(target string) (naming.Watcher, error) {
return &watcher{target}, nil
}
type watcher struct {
address string
}
func (w *watcher) Next() ([]*naming.Update, error) {
host, err := net.ResolveTCPAddr("tcp", w.address)
if err != nil {
return nil, nil
}
return []*naming.Update{{Op: naming.Add, Addr: host.String()}}, nil
}
func (w *watcher) Close() {
}
func main() {
r := &resolver{}
_, err := grpc.Dial("foobar.asdfasdf:1234", grpc.WithBalancer(grpc.RoundRobin(r)), grpc.WithInsecure())
if err != nil {
panic(err)
}
} It seems like it should be consistent one way or the other. |
In fact, I would suggest that this behaviour is contrary to the connectivity semantics described for the
And wait-for-ready:
|
…rvers This modifies the WithBlock behavior somewhat to block until there is at least one valid connection. Previously, each connection would be made serially until all had completed successfully, with any errors returned to the caller. Errors are now only returned due to connecting to a backend if a balancer is not used, or if there is an error starting the balancer itself. Fixes grpc#976
…rvers (#1112) This modifies the WithBlock behavior somewhat to block until there is at least one valid connection. Previously, each connection would be made serially until all had completed successfully, with any errors returned to the caller. Errors are now only returned due to connecting to a backend if a balancer is not used, or if there is an error starting the balancer itself. Fixes #976
hi, my question as below:
I use grpc balance, so I init a grpcclient use function grpc.Dial with parameter service name:
conn, err = grpc.Dial(servicename,...,grpc.WithBalancer(balancer))
the function grpc.Dial use DialContext, and my master routine will block here:
ch := cc.dopts.balancer.Notify()
if ch == nil {
// There is no name resolver installed.
addrs = append(addrs, Address{Addr: target})
} else {
addrs, ok = <-ch
if !ok || len(addrs) == 0 {
waitC <- errNoAddr
return
}
}
Because of no address available, there is not element([]Address) input into the channel.So, the dial will return "grpc: timed out when dialing".
if !ok || len(addrs) == 0 {
so dial will also return an error,and it is "grpc: there is no address available to dial" .
In our system, we have much processes implement different serivce. Unfortunately, these processes is a situation of mutual dependence. So I can't init any first process because i make it exit when dial fail, saddly this will lead to i can't start our system.
Actually I just hope dial return a grpc.ClientConn even if there is no address available.I think this can solve my problem.
The text was updated successfully, but these errors were encountered: