Skip to content
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

nsq_to_file: --topic-pattern causes connection leaks #935

Merged
merged 1 commit into from
Aug 28, 2017

Conversation

jxskiss
Copy link
Contributor

@jxskiss jxskiss commented Aug 27, 2017

ready for review

@jxskiss
Copy link
Contributor Author

jxskiss commented Aug 27, 2017

Improvement:
Initialize http client only when topicsFromNSQLookupd = true, that is --topic not provided and --topic-pattern provided.

@mreiferson mreiferson changed the title Fix issue #930 nsq_to_file --topic-pattern causes connection leaks nsq_to_file: --topic-pattern causes connection leaks Aug 27, 2017
@mreiferson mreiferson added the bug label Aug 27, 2017
@@ -514,8 +513,11 @@ func main() {
log.Fatal("use --topic to list at least one topic to subscribe to or specify at least one --lookupd-http-address to subscribe to all its topics")
}
topicsFromNSQLookupd = true
// initialize http client only when topicsFromNSQLookupd = true
// that is --topic not provided and --topic-pattern provided
discoverer.clusterInfo = clusterinfo.New(nil, http_api.NewClient(nil, connectTimeout, requestTimeout))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is necessary to avoid initializing it, seems harmless and unnecessarily complex

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of --topic provided, the connection is never used but never released, if one use nsq-to-file to read messages from many individual topics, then there will be many these connections.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're suggesting that clusterinfo.New makes an HTTP request just by initializing it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, may be I'm understanding http/transport wrong.
I'am not sure that will these codes in "nsq/internal/http_api/api_request.go" make a connection or the connection is only made when sending the exact http endpoint request?
Does the initialization of http client/transport require resource from OS?

// A custom http.Transport with support for deadline timeouts
func NewDeadlineTransport(connectTimeout time.Duration, requestTimeout time.Duration) *http.Transport {
	transport := &http.Transport{
		Dial: func(netw, addr string) (net.Conn, error) {
			c, err := net.DialTimeout(netw, addr, connectTimeout)
			if err != nil {
				return nil, err
			}
			return &deadlinedConn{connectTimeout, c}, nil
		},
		ResponseHeaderTimeout: requestTimeout,
	}
	return transport
}

type Client struct {
	c *http.Client
}

func NewClient(tlsConfig *tls.Config, connectTimeout time.Duration, requestTimeout time.Duration) *Client {
	transport := NewDeadlineTransport(connectTimeout, requestTimeout)
	transport.TLSClientConfig = tlsConfig
	return &Client{
		c: &http.Client{
			Transport: transport,
			Timeout:   requestTimeout,
		},
	}
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Connections should only be made when requests are made.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank your for the clarification, I will push a new commit soon later.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to clarify: the Transport and Client are just some structs with configuration (and function pointers etc), they just use a bit of memory (maybe a kilobyte or two). No file descriptors are created (or bound or connected) until a Dial or Request method is called.

@jxskiss
Copy link
Contributor Author

jxskiss commented Aug 28, 2017

The lazy initializing of clusterInfo has been reset.

@mreiferson
Copy link
Member

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants