Skip to content

GRPC: best way to connect to unix sockets - possible regression? #1846

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

Closed
tux21b opened this issue Feb 2, 2018 · 2 comments
Closed

GRPC: best way to connect to unix sockets - possible regression? #1846

tux21b opened this issue Feb 2, 2018 · 2 comments

Comments

@tux21b
Copy link

tux21b commented Feb 2, 2018

Previously, i used following code to support TCP and Unix sockets:

// SchemaDialer supports an optional protocol prefix
// (like "tcp://" or "unix://"). TCP is the default.
func SchemaDialer(addr string, timeout time.Duration) (net.Conn, error) {
	proto, addr := SplitSchemaAddr(addr)
	return net.DialTimeout(proto, addr, timeout)
}

// SplitSchemaAddr parses an address with an optional protocol prefix
// (like "tcp://" or "unix://"). TCP is the default.
func SplitSchemaAddr(addr string) (string, string) {
	parts := reSchema.FindStringSubmatch(addr)
	proto, addr := parts[1], parts[2]
	if proto == "" {
		proto = "tcp"
	}
	return proto, addr
}

var reSchema = regexp.MustCompile("^(?:([a-z0-9]+)://)?(.*)$")

The usage itself looked like grpc.Dial(addr, grpc.WithDialer(SchemaDialer)) and worked fine with previous GRPC versions. The value of addr is for example unix:///run/example.sock and the old GRPC behavior was that the value of addr gets passed to the dialer unmodified.

After a recent update to 1.9.2 the behavior has changed significantly. The address gets parsed before, the schema and the first slash gets removed and "run/example.sock" (note the relative path and missing schema) is passed to my SchemaDialer(). This all happens in the line cc.parsedTarget = parseTarget(cc.target) within grpc.DialContext() and is not configureable.

Without access to the original address, the addr parameter for the dialer is completely useless to me. I can probably ignore it and use a value from a closure, but I guess that's not the intended way.

Any help is appreciated! Many thanks!

@dfawley
Copy link
Member

dfawley commented Feb 2, 2018

@tux21b, I think you ultimately want a fix to #1741, which would make us support dialing unix sockets automatically.

In the meantime, our target parsing behavior is as described in our spec here: https://github.com./grpc/grpc/blob/master/doc/naming.md

Your "unix:///run/example.sock" is being parsed as:

  • "unix" as the schema
  • "" as the authority
  • "run/example.sock" as the endpoint_name

Because you want your dialer to see the entire target name, you can use the passthrough resolver like so:

import "..../grpc/resolver/passthrough"

grpc.Dial("passthrough:///unix:///run/example.sock")

We will support the unix scheme out of the box when #1741 is fixed, at which point you would use unix:////run/example.sock (note the four slashes up front: two after schema, one after authority, and one as the beginning of the endpoint name) or dns:///hostname.com or dns:///<numeric IP> (dns is installed by default).

Sorry for the change of behavior. The previous implementation did not follow the grpc spec, which was preventing us from supporting other features that we needed. Let me know if you have any other questions.

@dfawley dfawley closed this as completed Feb 2, 2018
@tux21b
Copy link
Author

tux21b commented Feb 5, 2018

@dfawley thanks for your detailed answer. The passthrough resolver seems like a good solution for the meantime. Many thanks for the tip!

@lock lock bot locked as resolved and limited conversation to collaborators Sep 26, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants