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 racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.