4

Sorry, I cannot find this answer from Google search and nobody seems to explain clearly the difference between pure Go webserver and nginx reverse proxy. Everybody seems to use nginx in front for web applications.

My question is, while Go has all http serving functions, what is the benefit of using nginx over pure Go web servers?

And in most cases, we set up the Go webserver for all routes here and have the nginx configurations in front.

Something like:

limit_req_zone $binary_remote_addr zone=limit:10m rate=2r/s;

server {
    listen 80;

    log_format lf '[$time_local] $remote_addr ;

    access_log /var/log/nginx/access.log lf;
    error_log /var/log/nginx/error.log;

    set_real_ip_from 0.0.0.0/0;
    real_ip_header X-Forwarded-For;
    real_ip_recursive on;
    server_name 1.2.3.4 mywebsite.com;
}

When we have this Go:

func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

Are the traffic to nginx and Go web server different? If not, why do we have two layers of web server?

Please help me understand this.

Thanks,

3 Answers3

6

There's nothing stopping you from serving requests from Go directly.

On the other hand, there are some features that nginx provides out-of-the box that may be useful, for example:

  • handle many virtual servers (e.g. have go respond on app.example.com and a different app on www.example.com)

  • http basic auth in some paths, say www.example.com/secure

  • access logs

  • etc

All of this can be done in go but would require programming, while in nginx it's just a matter of editing a .conf file and reloading the configuration. Nginx doesn't even need a restart for this changes to take place.

(From a "process" point of view, nginx could be managed by an ops employee, with root permissions, running in a well known port, while developers deploy their apps on higher ones.)

Pablo Fernandez
  • 103,170
  • 56
  • 192
  • 232
  • 2
    Good answer. Go can do a lot of this too, but you (as a developer) or your team need to decide where to draw the line on "writing stuff to suit our precise purposes" vs. "nginx does this for us already". nginx/HAProxy/Varnish are well tested tools and can save you reinventing several wheels. – elithrar Sep 04 '15 at 00:22
1

The general idea of using nginx in this scenario is to serve up static resources via nginx and allow Go to handle everything else.

Search for "try_files" in nginx. It allows for checking the disk for the existence of a file and serving it directly instead of having to handle static assets in the Go app.

sberry
  • 128,281
  • 18
  • 138
  • 165
1

This has been asked a few times before[1] but for posterity:

It depends.

Out of the box, putting nginx in front as a reverse proxy is going to give you:

  • Access logs
  • Error logs
  • Easy SSL termination
  • SPDY support
  • gzip support
  • Easy ways to set HTTP headers for certain routes in a couple of lines
  • Very fast static asset serving (if you're serving off S3/etc. though, this isn't that relevant)

The Go HTTP server is very good, but you will need to reinvent the wheel to do some of these things (which is fine: it's not meant to be everything to everyone).

I've always found it easier to put nginx in front—which is what it is good at—and let it do the "web server" stuff. My Go application does the application stuff, and only the bare minimum of headers/etc. that it needs to. Don't look at putting nginx in front as a "bad" thing.

Further, to extend on my answer there, there's also the question of crash resilience: your Go application isn't restricted by a configuration language and can do a lot of things.

Some of these things may crash your program. Having nginx (or HAProxy, or Varnish, etc.) as a reverse proxy can give you a some request buffering (to allow your program to restart) and/or serve stale content from its local cache (i.e. your static home page), which may be better than having the browser time out and serve a "cannot connect to server error".

On the other hand, if you're building small internal services, 'naked' Go web servers with your own logging library can be easier to manage (in terms of ops).

If you do want to keep everything in your Go program, look at gorilla/handlers for gzip, logging and proxy header middleware, and lumberjack for log rotation (else you can use your system's logging tools).

Community
  • 1
  • 1
elithrar
  • 23,364
  • 10
  • 85
  • 104