OTRS on Plack

Lately I've been playing around with the OTRS ticketing system on one of my servers. OTRS is written in Perl, and is typically run as a CGI, mod_perl or FastCGI app. Usually I'd map it as a FastCGI app on Nginx and start the 2 FastCGI servers via a init.d script (one for the customer helpdesk and another for the management console).

But this time I wanted to give Plack a try.

I'm new to Plack and PSGI, but I can't wait to start moving my apps to this badass middleware framework.

Plack comes with 2 CGI wrapper modules, Plack::App::WrapCGI and Plack::App::CGIBin. WrapCGI seems like the most appropriate for my needs. Apparently it even precompiles CGIs using CGI::Compile, for added performance.

So I wrote a little app.psgi in the /opt/otrs directory:

use Plack::App::CGIBin;
use Plack::Builder;
my $app_main = Plack::App::WrapCGI->new(script => "/opt/otrs/bin/cgi-bin/index.pl")->to_app;
my $app_customer = Plack::App::WrapCGI->new(script => "/opt/otrs/bin/cgi-bin/customer.pl")->to_app;
my $app_web = Plack::App::File->new(root => "/opt/otrs/var/httpd/htdocs")->to_app;
builder {
      mount "/otrs" => $app_main;
      mount "/helpdesk" => $app_customer;
      mount "/otrs-web" => $app_web;

And fired it off:

/opt/otrs $ plackup

OTRS was listening on the default http://localhost:5000/otrs and working flawlessly! But, naturally as it's running on plain plackup, it was a little slow handling requests. So I decided to upgrade it to the preforking Starman.

/opt/otrs $ starman

All I had to do was run the starman command-line, it uses the same app.psgi to spawn 5 processes. OTRS responsiveness was noticiable.

Now, following advice from the Starman's POD, I decided to preload some modules to get the benefits of copy-on-write on forking. I don't know the OTRS internals well, so I chose packages almost randomly.

/opt/otrs $ starman --preload-app -MDBD::mysql -MKernel::System::Ticket

That brought total reported memory usage for 5 Starman processes from 90K to 130K and slowed down startup a little. But after firing off many requests, the preloading started to pay off, reporting a stable 150K (preloaded), versus 200K+ (no preload).

My server is somewhat overloaded these days, but I decided to fire off some concurrency benchmarks anyway. Values are in reqs/sec.

serverNginx+FastCGI Starman Plackup
dynamic content11.77 18.34 9.18
static content23656.65 6892.42 225.54


Starman does a really good job handling concurrency for dynamic content. For obvious reasons, Nginx static handling blows anything away. So a good setup would be Nginx for static content and Starman as the centralized application server.

Hopefully, more and more legacy Perl apps will migrate to Plack. For the meanwhile, Plack seems like an excellent choice for centralizing Perl webapp management.


Have been playing with Plack and Starman today as well and the performance delivered by Starman is very impressive. Also, the ease of use is superb, especially when you're already using a framework like Catalyst or Dancer. But plain old CGI can easily be converted as well for what I've seen. I'm really happy to see all these great developments in the world of Perl.

It would be interesting to see how `Nginx+FastCGI` compares to `Nginx+FastCGI+Plack`. I.e. FastCGI provided through the Plack intermediary interface.

Great post!

avar: yes the FastCGI comparison would be interesting, even though Plack has *many* FastCGI options - with FCGI.pm + FCGI::ProcManager or Net::FastCGI. The latter is pure perl and chansen has been working on the performance improvement, but it hasn't got preforking support yet. More to come :)

Leave a comment

About rodrigolive

user-pic Perl and all things considered