3 ms·
The blog seems sadly unable to tolerate the load. I don't see an archived version of the post anywhere either. If I had to have a guess what it says, it's prob
by asdfasgasdgasdg 7y ago
The blog seems sadly unable to tolerate the load. I don't see an archived version of the post anywhere either.
If I had to have a guess what it says, it's probably something along the lines of:
* Don't require users of your API to start goroutines to use your API correctly.
If Goroutines need to be started for your API to work, start them in an init function, on first use, or via some other mechanism.
* If possible, avoid high goroutine fanout in your implementation.
If a single request to your API fans out to 1k goroutines, it's going to be a problem for a high-traffic user of your API. Especially if there are other APIs that make the same design choice. As ever, try to be parsimonious with resource consumption.
IMO, these are two good principles to live by, and not just in Go.
- jjbiotech 7y agoDoesn't the native net/http server spin up a goroutine for every request? Edit: See line 2927 at https://golang.org/src/net/http/server.go https://golang.org/src/net/http/server.go
- asdfasgasdgasdg 7y agoYeah, but it doesn't spin up a thousand for every request. And it doesn't require you to start them. It starts them under the covers as part of the API.
- jjbiotech 7y agoRight. So: * Don't require users of your API to start [additional] goroutines to use your API correctly.
- asdfasgasdgasdg 7y agoI guess what I mean to say is: don't make your users write go yourpackage.YourApiCall() in order to use the API correctly. That's just a guess, though.
- sagichmal 7y agoThe article says almost exactly the opposite, and I agree. Your API should present all of the things it does as synchronous functions/methods. If callers want to run them asynchronously, they can easily provide their own goroutine to do so, including whatever lifecycle management makes sense for them. The concrete example was // Do this func (t *type) Run(ctx context.Context) { ... } // Not this func (t *type) Start() { ... } func (t *type) Cancel() { ... } This is generally good advice which stops a whole class of extremely common and very tricky to debug orchestration bugs outright.
- gnoack 7y agoThe net/http library is the caller in this case, so that would be consistent with the rule that callers should start goroutines. Request handlers are a bit of a special case too, in that they are a framework for dispatching tasks to be worked on; what is main() for a command line program is the request handler for a webserver. It seems fair that there is some concurrency coordination happening at the top level.
- gnoack 7y ago(whoops, excuse the bad webserver config... should be fixed now) > Don't require users of your API to start goroutines to use your API correctly. Actually, what I postulate in the article is different... The theory is that making the caller kick off the goroutines puts more control over concurrency into the hands of the caller, and the resulting API is simpler. > Avoid high goroutine fanout in your implementation. That's for sure. :)