Webserver Deployment

254 views
Skip to first unread message

Caleb

unread,
Mar 3, 2011, 9:48:31 PM3/3/11
to golang-nuts
I've been using go as web server for a project and I'm trying to come
up with a good way of deploying the server. Currently I have a build
setup that compiles the binary and packages it and any resources (css/
js/images...) into a zip file. It then pushes that file out to the web
server and extracts it to a new folder. Then it kills the old web
server's process and starts up the new one.

I'm concerned about 2 things: (1) This is a server made up of
different logical applications... letting them all run in a single
process runs the risk of the whole server crashing, (2) I'm worried
that while its restarting connections will be dropped.

Most of the ideas I've investigated seem more trouble than they're
worth (at least for this small site)... is there an easy way to do
this that I'm not realizing?

Dave Cheney

unread,
Mar 3, 2011, 10:10:52 PM3/3/11
to Caleb, golang-nuts
I'm concerned about 2 things: (1) This is a server made up of
different logical applications... letting them all run in a single
process runs the risk of the whole server crashing,

Then you should probably split the applications into separate processes and use a reverse proxy like haproxy, nginx or varnish to present them in a single URL namespace. 

(2) I'm worried
that while its restarting connections will be dropped.

Take a look at the way nginx does binary upgrades. Their method is probably the most seamless without using a reverse proxy to stage your requests. 

Caleb

unread,
Mar 3, 2011, 11:04:56 PM3/3/11
to golang-nuts
Thanks I hadn't thought of the reverse proxy. That would make for a
very clean separation of my applications. (Though it'd still be nice
to somehow do this all in go...)

For the restart it looks like SO_REUSEADDR might do what I need? (Both
servers listen on the same port, then I close the original) I'll try
it out tomorrow.

madari

unread,
Mar 4, 2011, 1:59:56 AM3/4/11
to golan...@googlegroups.com
AFAIK, the trick is that upon receiving a signal (SIGUSR2) the old Nginx master spawns a new master instance of the binary with the listening socket in its
initial file descriptor set. After that they can both be accept():n on the socket. Then it's up to the user to terminate (gracefully by SIG<something>) the old master instance after observing that the new master works as expected

SO_REUSEADDR tells the kernel that a process can bind to an address which is in TIME_WAIT state. This is not what you are looking for, I think.
In some environments there is a flag SO_REUSEPORT which would be useful to you, but it's not portable.

Maybe someone else can elaborate more on this matter, or you could check the Nginx sources what it actually does.

Kai Backman

unread,
Mar 4, 2011, 7:32:00 AM3/4/11
to Caleb, golang-nuts
On Fri, Mar 4, 2011 at 4:48 AM, Caleb <caleb....@gmail.com> wrote:
> I'm concerned about 2 things: (1) This is a server made up of
> different logical applications... letting them all run in a single
> process runs the risk of the whole server crashing,

We deploy a user space process manager similar to daemontools that
handles our different logical applications. The main reason we don't
use deamontool directly is that we want to funnel stdout and stderr
(where the output of panic goes) into our custom logging system and
having our own process manager lets us wrap the process stdin/stdout.

> (2) I'm worried
> that while its restarting connections will be dropped.

If you run a web application you probably want to write the client
part in such a way that it can survive a connection drop and then just
ignore the problem initially. If you need to serve long running http
requests then Dave had some good suggestions.

Kai

--
Kai Backman, programmer
http://tinkercad.com - solid modeling for artists and makers

Reply all
Reply to author
Forward
0 new messages