-
Notifications
You must be signed in to change notification settings - Fork 580
Hypnotoad prefork web server
Mojo::Server::Hypnotoad is a built-in prefork web server in production environment. hypnotoad
is command line interface to run Mojolicious application by Mojo::Server::Hypnotoad.
Start Server.
hypnotoad myapp.pl
Server start on port 8080 by default. you can access it from web browser.
http://localhost:8080
Process ID file is created in the same directory.
hypnotoad.pid
hypnotoad myapp.pl --stop
hypnotoad myapp.pl
Hypnotoad will finish responding to existing requests; all new requests will use the reloaded code.
If you want to run server from root user, you switch application user and type hypnotoad
command.
su - appuser -c 'hypnotoad $HOME/webapp/myapp/myapp.pl'
And you add this into OS startup config file such as rc.local
/etc/rc.d/rc.local
If you are working under Mac OS X, you can use the command launchctl
and create a corresponding .plist file to run hypnotoad on startup. The following is a working example that you can save as
~/Library/LaunchAgents/us.mojolicio.hypnotoad.plist
Here is the script:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://
www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>us.mojolicio.hypnotoad.plist</string>
<key>RunAtLoad</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>hypnotoad</string>
<string>myapp.pl</string>
</array>
<key>WorkingDirectory</key>
<string>/Path/to/app/rootfolder</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>.:/opt/local/bin:$PATH</string>
</dict>
<key>StandardErrorPath</key>
<string>/Path/to/app/rootfolder/log/output.log</string>
<key>StandardOutPath</key>
<string>/Path/to/app/rootfolder/log/output.log</string>
</dict>
</plist>
Use the following command to install as autostart item, "unload" to remove.
launchctl load -w ~/Library/LaunchAgents/us.mojolicio.hypnotoad.plist
The format of these files and launchctl
is well documented - just google for launchctl plist and pick the Apple developer links.
In production deployment, generally proxy server is used to access hypnotoad server. The following is apache/mod_proxy config file example using virtual host.
<VirtualHost *:80>
ServerName app1.somehost.com
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
</VirtualHost>
See the various webserver sections under "DEPLOYMENT" in Mojolicious::Guides::Cookbook for details on reverse-proxying to your app, and for pointers on getting X-Forwarded-For
headers set and honoured by Mojo.
If you connect to database before preforking server and you use the connection to execute SQL, You see the following error in log or STDERR, for example, in MySQL.
MySQL server has gone away
The most simple solution is that you connect to database after preforking server. so you can establish the following two rules.
- 1. you must not connect to database in
startup
method. - 2. Database initialization process must be written as default value of
has
function orattr
method.
The following is Mojolicious and Mojolicious::Lite example.
Mojolicious:
package MyApp;
use Mojo::Base 'Mojolicious';
use DBI;
has dbh => sub {
my $self = shift;
my $data_source = "dbi:mysql:database=usertest";
my $user = "ken";
my $password = "ijdiuef";
my $dbh = DBI->connect(
$data_source,
$user,
$password,
{RaiseError => 1}
);
return $dbh;
};
sub startup {
my $self = shift;
# You must not connect to database.
# Routes
my $r = $self->routes;
# Normal route to controller
$r->route('/welcome')->to('example#welcome');
}
1;
You use dbh
from controller.
package MyApp::Example;
use Mojo::Base 'Mojolicious::Controller';
# This action will render a template
sub welcome {
my $self = shift;
my $dbh = $self->app->dbh;
my $sth = $dbh->prepare('select * from table1');
$sth->execute;
$self->render(text => 'Hello');
}
1;
Mojolicious::Lite
use Mojolicious::Lite;
use DBI;
# You must not connect to database in this location
# dbh attribute
app->attr(dbh => sub {
my $self = shift;
my $data_source = "dbi:mysql:database=test";
my $user = undef;
my $password = undef;
my $dbh = DBI->connect($data_source, $user, $password);
return $dbh;
});
get '/' => sub {
my $self = shift;
my $dbh = $self->app->dbh;
my $sth = $dbh->prepare('select * from table1');
$sth->execute;
$self->render(text => 'Hello');
};
app->start;
Best way to to solve database connection problem in preforking is using DBIx::Connector. DBIx::Connector is database connection manager. Even if database connection is closed, the connection is automatically re-established.
my $connector = DBIx::Connector->new(
"dbi:mysql:database=$database",
$user,
$password,
);
my $dbh = $connector->dbh;
Some DBI wrapper modules support DBIx::Connector.
DBIx::Custom support DBIx::Connector.
my $connector = DBIx::Connector->new(
"dbi:mysql:database=$database",
$user,
$password,
{
%{DBIx::Custom->new->default_dbi_option},
mysql_enable_utf8 => 1
}
);
my $dbi = DBIx::Custom->connect(connector => $connector);