No performance improvement on nginx reverse-proxy

Hello,

This day I did a simpe test with nginx’s reverse-proxy.
The environment is on a vmware virtual host.

OS: slackware Linux, kernel 2.6.24.5-smp
CPU: Intel(R) Celeron(R) CPU 723 @ 1.20GHz
MEM: 350M

The application environment:

nginx version: nginx/0.8.52
apache version: Apache/2.2.15 (Unix)
mysql version: 5.1.51

The performance/capability arguments for nginx/apache are:

[nginx]

worker_processes 8;
events {
worker_connections 1024;
}

[apache]

StartServers 5 MinSpareServers 5 MaxSpareServers 10 MaxClients 150 MaxRequestsPerChild 0

Apache run with two vhosts, one is listening on 8080 port, another is
listening on 8081 port.

The vhost config shown as below:

<VirtualHost *:8080>
DocumentRoot “/usr/local/apache2.2/vhost/vh1”
ScriptAlias /cgi/ “/usr/local/apache2.2/vhost/vh1/cgi/”

<VirtualHost *:8081>
DocumentRoot “/usr/local/apache2.2/vhost/vh2”
ScriptAlias /cgi/ “/usr/local/apache2.2/vhost/vh2/cgi/”

There are two cgi scripts on the cgi dirs above.
one is /usr/local/apache2.2/vhost/vh1/cgi/test.cgi
another is /usr/local/apache2.2/vhost/vh2/cgi/test.cgi

Their content is do the same.
It’s a simple perl script which fetches a record by random from a
table which has 150,000 records totally.
[the script content is pasted on the last of this message.]

Nginx is setup for the reverse-proxy to the two vhosts of apache.
The config piece shown as:

upstream MyTestServ {
  server 127.0.0.1:8081;
  server 127.0.0.1:8080;
}

server {
    server_name my.test.com;
    listen 80;

    location / {
      proxy_set_header Host  $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_pass http://MyTestServ;
    }
}

After all that done, I tested it with http_load (a tool from
http_load).

./http_load -parallel 15 -seconds 30 urls

This test nginx for rever-proxy, the url is like:
http://192.168.0.77/cgi/test.cgi

./http_load -parallel 15 -seconds 30 urls1

This test apache directly, the url is like:
http://192.168.0.77:8080/cgi/test.cgi

After testing for some times (have been changing the arugments for
http_load), I found nginx with reverse-proxy is not better than the
realserver.
Even the result is worse for accessing nginx than access apache
directly.

The result with nginx reverse-proxy:

191 fetches, 15 max parallel, 9782 bytes, in 30 seconds
51.2147 mean bytes/connection
6.36667 fetches/sec, 326.067 bytes/sec
msecs/connect: 1.23155 mean, 3.663 max, 0.648 min
msecs/first-response: 2250.49 mean, 5026.69 max, 576.448 min
90 bad byte counts
HTTP response codes:
code 200 – 191

The result with NO reverse-proxy:

196 fetches, 15 max parallel, 10030 bytes, in 30.0005 seconds
51.1735 mean bytes/connection
6.53322 fetches/sec, 334.327 bytes/sec
msecs/connect: 1.35084 mean, 6.877 max, 0.797 min
msecs/first-response: 2103.1 mean, 4348.94 max, 535.809 min
84 bad byte counts
HTTP response codes:
code 200 – 196

So how do you think about it?
Suggestions are welcome. Thanks.

END

This is the CGI script for testing:

#!/usr/bin/perl
use strict;
use CGI;
use DBI;

my $q=CGI->new;
print $q->header(“text/plain”);

my $dsn = “DBI:mysql:database=pyh;host=127.0.0.1;port=3306”;
my $dbh = DBI->connect($dsn, ‘root’, ‘’);

my $id = 10026 + int(rand(150000));

my $str = “select * from myt2 where id = $id”;
my $sth = $dbh->prepare($str);
$sth->execute;

my @array = $sth->fetchrow_array;
$sth->finish;
$dbh->disconnect;

print “@array\n”;

On Wed, 2010-10-13 at 12:33 +0800, yung wrote:

After testing for some times (have been changing the arugments for
http_load), I found nginx with reverse-proxy is not better than the
realserver.
Even the result is worse for accessing nginx than access apache directly.

So how do you think about it?
Suggestions are welcome. Thanks.

If you use a Ferrari to tow a dump truck, you will find that the dump
truck actually goes slightly faster on its own.
In short, there are so many bottlenecks in your test setup (Apache, CGI,
database) that the speed differences you see are probably not even
statistically significant.

Further, it’s not clear at all why you think adding additional layers of
processing (a proxy) to your stack would somehow magically speed things
up. Of course it will be slower. How could you ever expect
anything different? The typical use-case of Nginx in front of Apache
is to allow Nginx to serve static resources to take the load away from
Apache. You could also use some of Nginx’ caching features to take
load off Apache. You did none of these things. I think you need to
think harder about what you are testing.

Regards,
Cliff

On Wed, Oct 13, 2010 at 12:33:17PM +0800, yung wrote:

The application environment:
worker_processes 8;
MaxClients 150
DocumentRoot “/usr/local/apache2.2/vhost/vh1”
one is /usr/local/apache2.2/vhost/vh1/cgi/test.cgi

      proxy_set_header Host  $host;

51.2147 mean bytes/connection
196 fetches, 15 max parallel, 10030 bytes, in 30.0005 seconds
Suggestions are welcome. Thanks.
nginx is not a magic wand, it’s just a reverse proxy.
It can help if a bottleneck is a slow client.
In your case bottlenecks are CGI script launches and database queries,
so nginx adds only an overhead as you have seen: 6.5 req/s vs 6.3 req/s.

print $q->header(“text/plain”);
my @array = $sth->fetchrow_array;
$sth->finish;
$dbh->disconnect;

print “@array\n”;


Igor S.
http://sysoev.ru/en/

The only time you will see a performance increase from nginx as a
reverse
proxy is when you need features that apache does badly like keep alive.

On Wed, Oct 13, 2010 at 05:18:14PM +1100, SplitIce wrote:

The only time you will see a performance increase from nginx as a reverse
proxy is when you need features that apache does badly like keep alive.

Not only keep alive - just long enough download, even 1 second:
if an Apache process creates response in 50ms, there is no sense to keep
the huge process bound to a slow client for 1s, because the process
can create resposnes for 20 clients for this second.

Suggestions are welcome. Thanks.
up. Of course it will be slower. How could you ever expect
anything different? The typical use-case of Nginx in front of Apache
is to allow Nginx to serve static resources to take the load away from
Apache. You could also use some of Nginx’ caching features to take
load off Apache. You did none of these things. I think you need to
think harder about what you are testing.


Igor S.
http://sysoev.ru/en/

Vg