
On Concurrency in Go HTTP Servers - signa11
https://eli.thegreenplace.net/2019/on-concurrency-in-go-http-servers/
======
perfmode
Ugh. This is only going to mislead newbies and irritate the experienced people
who will end up reviewing their code.

Channel sends and receives have non-trivial costs associated with them.

When you choose to model your problem with channel communication, you better
be sure you’re doing enough work before and/or after the send/recv to justify
involving the scheduler.

I’ve reviewed code where new engineers spawn unbounded goroutines... for each
goroutine to then go on to compute the distance between two points on a two
dimensional plane... aggregate the results on a channel and compute a sum.

~~~
zzzcpan
Say channels were always low overhead, two orders of magnitude faster in
general or optimized out completely in cases where even that overhead was too
much. Would it still make a difference?

I believe performance is only a small part of the problem, channels in Go are
just too awkward to use.

~~~
swiley
I haven't done a ton of go programming but the last small web app I wrote we
sent closures over a channel to serialize access to a sqlite database.
Channels felt like a nice clean way to handle that.

~~~
iainmerrick
Yes, sending closures over channels is a very convenient and flexible
concurrency framework. In fact it would be handy for all channels to have a
standard handler attached, that pulls closures from the channel and executes
them. Among other benefits that would mean you didn’t need a separate “go”
keyword; to execute a function in the background you just post it to a
channel. That’s basically how Java thread pools and Grand Central Dispatch
work.

The idiom of defining message types that you post to a channel so that you can
pull them from the channel and execute them strikes me as boilerplate. What
you really want to do is run some code in a particular thread context; so why
not just do that directly?

Are there useful things you do with channels that can’t easily be done with
thread pools?

------
TXV
I think this is a rather confusing article for beginners. I would say that
request processing in an HTTP framework isn’t exactly a practical use case to
demonstrate Go concurrency features. Most real-world applications are based on
REST, which is stateless. In fact I would not associate HTTP server frameworks
(in Go or in whatever language) with internal shared state management in an
entry level article. For people interested in Go concurrency features there’s
this great curated list instead:

[https://github.com/golang/go/wiki/LearnConcurrency](https://github.com/golang/go/wiki/LearnConcurrency)

~~~
mikece
I am unfamiliar with how Go HTTP frameworks do things but in Elixir each
request is a new process... and running in BEAM which was designed for massive
concurrency from the beginning. Go is frequently compared to BEAM solutions so
I'm curious if each request in a Go web framework spawns a separate process
per request.

~~~
zzzcpan
Go shouldn't be compared to BEAM at all. It doesn't have processes. It spawns
a lightweight thread (goroutine) on each request.

~~~
kitd
BEAM's "processes" are lightweight too AIUI, pretty similar to goroutines.

------
kasey_junk
Seems odd not to mention sync.Map at least in passing.

~~~
geoka9
It's got a lot of gotchas and is not intended to be a simple replacement for
map+mutex (certainly not in this case).

~~~
blaisio
Actually, this is exactly a scenario in which a sync.Map would be useful.
Typically, you would use pointers to atomic integers as the sync.Map values in
a case like this.

------
Blackstone4
In most situations shouldn’t you be storing state-like items like counters in
your db which is atomic in any case?!

~~~
SamWhited
This isn't the kind of thing anyone can answer without a real world scenario.
An abstract problem like a counter may or may not need to be in the DB, and
just because you have a DB doesn't mean you should rely on it for locking or
atomicity (maybe you have a read replica and your writes/reads are happening
in different places, maybe the data is only useful temporarily and if the
service dies it doesn't matter that it's lost, etc.)

