I probably wasn't very clear about what's going on with Unicorn when I 
deploy a new version of the app. It's actually quite simple, and doesn't 
require loading new code on the fly. Here's what I do:

1) I update the app server code via:  git pull  (this doesn't affect the 
running processes due to Linux inode handling)
2) I send a signal to the Unicorn master process via:  kill -USR2 <pid>
3) Unicorn then instructs each of the worker processes to quit after 
finishing their current request, if any.
4) When each worker process quits, Unicorn automatically spins up a new one 
that happens to use the new code

Requests continue to be handled by existing worker processes, so there's no 
downtime.

I'm not too concerned about this aspect - I could easily instrument this 
manually by making the worker processes accept a signal/message/etc. that 
would instruct them to quit after the current request.

The monit solution seems fine, but it typically works via a pid file, so 
I'd simply have to ensure that the N Racket server processes write their 
respective pid's to N separate files. It's not a big deal, but having 
something like Unicorn handle that is handy. 

I could probably just have monit pass a unique argument to each of the N 
processes e.g. 1, 2, 3, ... , N and store the pid's in pid1, pid2, ... , 
pidN. They could also use the arg to form the port they listen on 4311, 
4312, ... , 431N

I'm probably going to be dealing with only 2 or 4 cores typically, so the 
final solution doesn't need to be all that complicated.

I appreciate all the info folks have supplied, and I learned something new 
from George about multiple apps listening on the same port - I assume that 
involves SO_REUSE - I may have to research that. Having the OS handle the 
scheduling may be worth considering.

On Saturday, November 24, 2018 at 2:21:11 PM UTC-5, Jesse Alama wrote:
>
> Hi Brian, 
>
> On 23 Nov 2018, at 21:46, Brian Adkins wrote: 
>
> > I'm porting a web application from Ruby/Rails to Racket, and I'd like 
> > something to manage the Racket server processes. 
> > 
> > In the Ruby world, I'm currently using Unicorn ( 
> > https://en.wikipedia.org/wiki/Unicorn_(web_server) ) prior to that I 
> > used 
> > Nginx Passenger ( https://en.wikipedia.org/wiki/Phusion_Passenger ), 
> > etc. 
> > Another popular Ruby app server is Puma 
> > ( https://en.wikipedia.org/wiki/Puma_(web_server) ) 
> > 
> > I'll use nginx as the front end web server, and it will proxy to the 
> > application server. In a nutshell, for Unicorn, I configure the 
> > location of 
> > the Rails app, configure how many processes I want, and Unicorn will 
> > spin 
> > up that number of Rails processes and handle routing requests from 
> > nginx to 
> > each of the Rails processes in some fashion. If a Rails process exists 
> > abnormally, it will spin up another one to replace it. To deploy a new 
> > version of my app, I can send a signal to the Unicorn master process 
> > to 
> > *gracefully* restart all the processes i.e. it waits for the current 
> > request to finish, and then kills the process and spins up a new one 
> > using 
> > the new version of the app. 
> > 
> > Are there similar application servers available for Racket? 
> > Alternatively, 
> > if not, and you have long running applications in Racket, what are you 
> > using to manage them? 
>
> Just to echo the experience of others here: I've also used the Racket 
> server straight up on the unfiltered Internet, and had no problems 
> except (as Greg mentioned) weird requests flowing in that the server 
> found dubious. Without crashing, I should add; these weird (if not 
> downright malformed) requests didn't kill the web server, they just 
> created a lot of junk in the logs. Putting Racket behind a server that's 
> more prepared to handle such junk (e.g., OpenBSD's httpd) restores log 
> sanity. 
>
> To get back to your real question, though: you want to know how to 
> deploy a new version of a running web app. 
>
> (1) There's the reloadable package 
>
> https://pkgs.racket-lang.org/package/reloadable 
>
> I myself haven't used it, but it's definitely relevant. That looks like 
> a real Racket-y solution, which is what I think you're looking for. 
>
> (2) I myself view these issues as DevOps-y things to be dealt with not 
> so much in Racket and more at the OS/service level. Generating an 
> httpd.conf file and then using OpenBSD's rcctl to switch out the old 
> config for the new one has been fine for me. This is perhaps a deviant 
> view; the reloadable package probably reflects a more catholic 
> understanding of the situation. But there may be cases where you change 
> your code in ways that are just too big, and I bet you'll find yourself 
> needing to do something like what I do and what you're currently doing 
> with Unicorn. 
>
> Jesse 
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to