How do you deploy a PSGI script in Apache without restarting? - perl

I want to deploy a PSGI scripts that runs in Apache2 with Plack. Apache is configured with:
<Location "/mypath">
SetHandler perl-script
PerlResponseHandler Plack::Handler::Apache2
PerlSetVar psgi_app /path/to/my/script.psgi
</Location>
When I test the script with plackup, the --reload parameter watches updates on the .psgi file. In the production environment it is fine that Apache and Plack do not check and restart on each change for performance reasons, but how can I tell them explicitly to restart Plack::Handler::Apache2 and/or the PSGI script to deploy a new version?
It looks like Plack regularly checks for some changes but I have no clue when. Moreover it seems to create multiple instances, so I sometimes get different versions of script.psgi when at /mypath. It would be helpful to manually flush perl response handler without having to restart Apache or to wait for an unknown amount of time.

The short answer is you can't. That's why we recommend you to use plackup (with -r) for quick development and use Apache only for deployment (production use).
The other option is have a development apache process, and set MaxRequestsPerChild to a really small value, so that you will get a fresh child spawned in a very short period of time. I haven't tested this, and doing so will definitely impact the performance of your entire httpd, if you run the non-development application running on the same process (which is a bad idea in the first place anyway).

Apache2::Reload (untested)

You can move your application out of the appache process,
e.g.
FastCgiExternalServer /virtual/filename/fcgi -socket /path/to/my/socket
an run your programm with
plackup -s FCGI --listen /path/to/my/socket --nproc 10 /path/to/my/script.psgi
This way you can restart your application without restarting apache.
if you save the pid of the main fcgi process (--pid $pid_file)
you can easyly restart an load your new code.
There is also a module avail to manage (start,stop, restart) all your fcgi pools:
https://metacpan.org/pod/FCGI::Engine::Manager::Server::Plackup (not tested)

Related

Nginx FastCGI Perl configuration

I am trying to get FastCGI to work with Perl CGI in FastCGI mode. By that I mean that I can run Perl CGI scripts on Nginix without any issues but it does not appear (based on performance measurements) that my scripts are running in FastCGI mode. I've seen mentions about spawn-fcgi but nothing recent or details on how to implement with current versions of Nginx and Ubuntu.
I am relatively new to Linux.
Environment info:
Ubuntu 22.04 hosted in the "cloud"
nginx version: nginx/1.18.0 (Ubuntu)
Tutorial I followed: https://techexpert.tips/nginx/perl-cgi-nginx/
I have installed fcgiwrap.
CGI works, HTTPS works.
I am enclosing the bulk of my Perl CGI script within
use CGI::Fast;
while(my $q = new CGI::Fast)
{
# all my code
}
My script is doing a simple write and query from a very small SQLite3 database (4 columns, 500 rows, 290k db size).
I am testing across the Internet.
Script execution performance is about half of a second (.42 seconds per page) or 345ms. That is about the same as IIS Windows CGI.
I also saw that requesting a simple HTML file only has marginally better performance.
I understand that there is a lot more to performance testing than the preceding. The point is that I think there is something missing with my FastCGI configuration. I imagine it has something to do with me needing to launch the Perl FastCGI script somehow and then somehow connect that to Nginx. If anyone can point me in the right direction or provide example config files, that would be great. Thanks all!

Terminate running perl script started with CGI

I am creating a Perl script that creates a Net::WebSocket::Server on port 3000. Now I had the (not so brilliant) idea to start the script in the browser via CGI, so it runs in the background and can't be stopped. However, I have to restart the script whenever I modify it.
Is it possible to stop a CGI script in an endless loop, except by restarting the computer?
You didn't say what operating system you are on, so we cannot give you specific advice on how to find and kill the process. But you can always restart the web server application. CGI scripts are children of the server process (probably an Apache) that starts them. If you simply restart the Apache server, they should all be terminated.
Please don't put code that is supposed to run persistently in your cgi-bin directory. That's a bad idea, as you discovered.

How to run the Play's dist file in the background?

When I deployed my play application I built the package using:
dist
This created a file that I can run on my server like:
sudo ./bin/app-name -Dhttp.port=9090
This works fine for testing but how can I run this process in the background?
I will eventually have to use upstart or some sort of process monitoring tool to make sure this process is running after server reboots etc.
Using play 2.3.x
Since you are on ubuntu
sudo ./bin/app-name -Dhttp.port=9090 &
should do the trick.
Ceating the upstart script is also fairly easy https://askubuntu.com/questions/18802/how-to-correctly-add-a-custom-daemon-to-init-d
In your case it would be in /etc/init/app-name.conf and look like
# app-name
#
start on stopped rc RUNLEVEL=[2345]
stop on runlevel [!2345]
respawn
exec $PATH_TO_APP/bin/app-name -Dhttp.port=9090
Of course you will want to change the RUNLEVEL and the PATH_TO_APP
That of course depends on the system at which you're deploying the app, anyway in general you need to run it as a deamon.
Refer to your system's documentations, I'm pretty sure that you will find tutorial very soon.

Change site configuration without restarting G-WAN

I'm looking at hosting a number of small, static websites and have been looking at a few alternatives including G-WAN. At the moment I'm just trying to get a feel for how well each server suits my needs before picking one.
G-WAN seems to do exactly what I want, though I'm running into problems with updating the configuration (by adding new folders) after the server's started. I can't find anything in the documentation or online about this, so I don't know if I'm doing anything dumb, running an unsupported configuration, or whether it's a feature that doesn't exist in G-WAN.
Here's my setup:
G-WAN 3.3.28 64-bit on Ubuntu 12.04.1 LTS.
I have what I think is the required minimal folder structure:
0.0.0.0_80
#0.0.0.0
www
$site.com
www
$othersite.com
www
I startup gwan via (I'm still messing around, so hopefully ):
sudo .\gwan -d
Everything works brilliantly. I add $thirdsite.com/, $thirdsite.com/www/, and $thirdsite.com/www/index.html; then when I try to visit thirdsite.com it gives me the root host (ie it doesn't seem to pick up the changes).
To reload the modified configuration, I have to either do:
sudo .\gwan -k; sudo .\gwan -d
or kill the non-angel process (kill -s 15) to restart the child process.
Can G-WAN reload the host definitions another way? If so, is it something that works out of the box or is there a command that can cycle the server without dropping requests made to other hosts (/is it safe to kill -s 15 on the non-angel process + if so, is there a reliable way to identify the process)? Thanks in advance!
G-WAN loads the host definitions at startup and does not check them as time goes to reload them dynamically.
To force a reload, you have to stop the child process (when in daemon mode) and v3.9+ keeps the old child alive the time to process any pending request while the new child accepts new connections.
Since stopping the child can also be done from the maintenance script or from a handler or from a servlet by just running exit(0) there is not need for a dedicated command.
Note that when you use kill you can pick the pid file from the gwan directory:
the parent process starts with a capital letter: Gwan_xxxx.pid
the child process starts with a lowercase letter: gwan_xxxx.pid
That will make your life easier.

How do I get mod_perl to recognize changes to my application?

I'm running an apache2 / mod_perl2 combo on our development server.
When I'm developing, my changes are instantly reflected in the webpage I'm working on. I assumed mod_perl was being clever and was reloading files when they were changed.
But now another developer is working on a different part of the system and their changes are not picked up by mod_perl. He has to restart apache before he can see his changes.
Is there a way to disable caching on our development server, or get mod_perl to pick up his changes?
Thanks.
EDIT: I'm editing file directly on the dev server using VI, the other developer has mounted their dev directory via samba, and is editing their files in windows. This seems to be the difference that prevents mod_perl picking up changes.
I just read a nice blog post that sums up all possible ways to achieve this: How not to restart mod_perl servers by Jonathan Swartz
What exactly is the other developer changing?
To reload modules when they have changed you would use Apache2::Reload. (Though see Performance Issues before thinking about using this in production.)
Even without that, mod_perl will reload cgi scripts when they change; I don't know of any way the other developer could have turned that off if you are talking about cgi scripts.
Since it's just for development, how about just killing all of the child processes and letting the parent apache process respawn?
kill -9 $(ps axf | grep httpd | egrep -e ' S ' | cut -b1-5 | paste -s -d ' ')
The above command works for me on my box in my environment, your mileage will vary.
It's not an elegant solution by any means, but hey, it's faster than a full apache restart.